MAC端屏幕水印

Objective-C

Posted by YiMiTuMi on February 27, 2023

MAC端屏幕水印

通过新建一个NSPanel,然后在NSPanel上面添加一个NSView,再在NSView上面添加一个图层来显示水印。

初始化NSPanel

先设置一个NSPanel

NSPanel *pNSPanel = [[NSPanel alloc] initWithContentRect: NSScreen.mainScreen.frame styleMask: NSTitledWindowMask | NSClosableWindowMask | NSTitledWindowMask backing: NSBackingStoreBuffered defer: YES];

设置背景:颜色为透明、无边框

[pNSPanel setBackgroundColor: NSColor.clearColor];
[pNSPanel setOpaque: NO];       //设置透明
[pNSPanel setHasShadow: NO];
[pNSPanel setStyleMask: NSWindowStyleMaskBorderless];

设置图层比NSMainMenuWindowsLevel高一级,此时可以保证NSPanel始终显示在屏幕最上方,不会被其他窗口覆盖

[pNSPanel setLevel: kCGMainMenuWindowLevel + 1];
//[pNSPanel setCollectionBehavior: NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary];

使水印支持全屏、多桌面

[pNSPanel setHidesOnDeactivate: NO];
//[pNSPanel setCollectionBehavior: NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorStationary];

设置水印窗口忽略鼠标事件

[pNSPanel setIgnoresMouseEvents: YES];
[pNSPanel setDisplaysWhenScreenProfileChanges: YES];

创建一个NSView

因为无法直接在NSPanel上面设置图层所以需要设置一个NSView进行托管图层。创建一个View:

NSView *pView = [[NSView alloc] initWithFrame: pNSPanel.frame]; //初始化的大小为NSPanel的大小

Mac OS中使用CATextLayer时,需要先设置someview.wantsLayer = YES;否则加载不出来。

pView.wantsLayer = YES;

pNSPanel.contentView = pView;  //降Pview放置到NSPanel
[pNSPanel makeKeyAndOrderFront: nil];	

创建显示文本的图层

这里没有使用CATextLayer中对文本的设置,而是使用NSMutableAttributedString来设置文本。使用CATransform3D来设置倾斜度。

CATextLayer *pTextLayer = [CATextLayer layer];
pTextLayer.frame = pNSPanel.frame;

pTextLayer.string = pNsAttStr; //文本
//pTextLayer.alignmentMode = kCAAlignmentCenter; //居中
//pTextLayer.foregroundColor = [NSColor blackColor].CGColor; //设置颜色
//pTextLayer.fontSize = 30; //字体大小
pTextLayer.contentsScale = 2.0;
pTextLayer.wrapped = YES;  //设置文本是否只限制在frame中

//旋转
pTextLayer.transform = rotation;

//限制显示文本的范围 pTextLayer.bounds = CGRectMake(0, 0, 40 * pStrWaterText.length, 50);

//显示在屏幕坐标点的位置 pTextLayer.position = CGPointMake(0, 0);

//在view上添加图层
[pView.layer addSublayer: pTextLayer];   

NSMutableAttributedString来设置文本

初始化一个NSMutableAttributedString

NSString *pStrWaterText = @"屏幕水印测试";
NSMutableAttributedString *pNsAttStr = [[NSMutableAttributedString alloc] initWithString: pStrWaterText];

字体大小

[pNsAttStr addAttribute:(NSString *)kCTFontAttributeName     //字体大小
                     value:[NSFont systemFontOfSize: 40.0f]
                     range:NSMakeRange(0, pStrWaterText.length)];

颜色,不能设置整体的透明度,但是可以设置颜色的透明度(所以颜色和透明度一起设置)颜色接受的是一个RGB,alpha是透明度

[pNsAttStr addAttribute:(NSString *)NSForegroundColorAttributeName
                  value:[NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:0.1f]
                  range:NSMakeRange(0, pStrWaterText.length)];

NSMutableAttributedString富文本的属性值还有很多可以自行查找。

CATransform3D设置水印的倾斜度

CATransform3DMakeRotation函数的第一个参数接受的是一个弧度,所以要将度数转弧度:

double Radians(float degrees)
{
    return (degrees * M_PI) / 180;
}

设置旋转

CATransform3D rotationLeft45 = CATransform3DMakeRotation(Radians(45.0), 1, 1, 1); //左倾斜 45度
CATransform3D rotationLeft30 = CATransform3DMakeRotation(Radians(30.0), 1, 1, 1); //左倾斜 30度
CATransform3D rotationRight45 = CATransform3DMakeRotation(Radians(45.0), -1, -1, -1); //右倾斜 45度
CATransform3D rotationRight30 = CATransform3DMakeRotation(Radians(30.0), -1, -1, -1); //右倾斜 30度

完整代码

#import <Cocoa/Cocoa.h>
#import <QuartzCore/CALayer.h>
#import <QuartzCore/CATextLayer.h>


//度数转弧度
double Radians(float degrees)
{
    return (degrees * M_PI) / 180;
}


int main(int argc, const char * argv[])
{
   //初始化NSPanel
    NSPanel *pNSPanel = [[NSPanel alloc] initWithContentRect: NSScreen.mainScreen.frame styleMask: NSTitledWindowMask | NSClosableWindowMask | NSTitledWindowMask backing: NSBackingStoreBuffered defer: YES];
     
    //设置背景:颜色为透明、无边框
    [pNSPanel setBackgroundColor: NSColor.clearColor];
    [pNSPanel setOpaque: NO];       //设置透明
    [pNSPanel setHasShadow: NO];
    [pNSPanel setStyleMask: NSWindowStyleMaskBorderless];
    
    //设置图层比NSMainMenuWindowsLevel高一级,此时可以保证NSPanel始终显示在屏幕最上方,不会被其他窗口覆盖
    [pNSPanel setLevel: kCGMainMenuWindowLevel + 1];
    //[pNSPanel setCollectionBehavior: NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary];
    
    //使水印支持全屏、多桌面
    [pNSPanel setHidesOnDeactivate: NO];
    //[pNSPanel setCollectionBehavior: NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorStationary];
    
    //设置水印窗口忽略鼠标事件
    [pNSPanel setIgnoresMouseEvents: YES];
    [pNSPanel setDisplaysWhenScreenProfileChanges: YES];
    
    //创建一个View
    NSView *pView = [[NSView alloc] initWithFrame: pNSPanel.frame];
    pView.wantsLayer = YES;
    
    pNSPanel.contentView = pView;
    [pNSPanel makeKeyAndOrderFront: nil];
    
    
    //设置文本属性
    NSString *pStrWaterText = @"啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊";
    NSMutableAttributedString *pNsAttStr = [[NSMutableAttributedString alloc] initWithString: pStrWaterText];
    

    //设置文本样式
    /*
   [pNsAttStr addAttribute:(NSString *)kCTForegroundColorAttributeName     //颜色
                      value:(id)[NSColor redColor].CGColor
                      range:NSMakeRange(0, pStrWaterText.length)];
    */
    
    [pNsAttStr addAttribute:(NSString *)kCTFontAttributeName     //字体大小
                      value:[NSFont systemFontOfSize: 40.0f]
                       range:NSMakeRange(0, pStrWaterText.length)];
    
    //颜色,不能设置整体的透明度 但是可以设置 颜色的透明度
    //NSColor *pColor = [NSColor colorWithCalibratedRed:0 green:1 blue:0 alpha:1.0f];
    
    [pNsAttStr addAttribute:(NSString *)NSForegroundColorAttributeName
                      value:[NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:0.1f]
                       range:NSMakeRange(0, pStrWaterText.length)];
    
    /*
    [pNsAttStr addAttribute:(NSString *)NSStrokeWidthAttributeName  //文本中空
                      value:[NSNumber numberWithFloat:1]
                       range:NSMakeRange(0, pStrWaterText.length)];
    */
    
    [pNsAttStr addAttribute:(NSString *)NSObliquenessAttributeName
                      value:[NSNumber numberWithFloat:50]
                       range:NSMakeRange(0, pStrWaterText.length)];
    
    
    //设置旋转
    CATransform3D rotation = CATransform3DMakeRotation(Radians(45.0), 1, 1, 1); //左倾斜 45度
    //CATransform3D rotation = CATransform3DMakeRotation(Radians(30.0), 1, 1, 1); //左倾斜 30度
    
    //CATransform3D rotation = CATransform3DMakeRotation(Radians(45.0), -1, -1, -1); //右倾斜 45度
    //CATransform3D rotation = CATransform3DMakeRotation(Radians(30.0), -1, -1, -1); //右倾斜 30度
    
    CATextLayer *pTextLayer = [CATextLayer layer];
    pTextLayer.frame = pNSPanel.frame;
    
    pTextLayer.string = pNsAttStr; //文本
    //pTextLayer.alignmentMode = kCAAlignmentCenter; //居中
    //pTextLayer.foregroundColor = [NSColor blackColor].CGColor; //设置颜色
    //pTextLayer.fontSize = 30; //字体大小
    pTextLayer.contentsScale = 2.0;
    pTextLayer.wrapped = YES;  //设置文本是否只限制在frame中
    
    //倾斜
    pTextLayer.transform = rotation;
    
    //限制显示文本的范围
    pTextLayer.bounds = CGRectMake(0, 0, 40 * pStrWaterText.length, 50);
    
    //显示在屏幕坐标点的位置
    pTextLayer.position = CGPointMake(500, 700);
    
    //在view上添加图层
    [pView.layer addSublayer: pTextLayer];
    
    
    /*---------------显示第二个--------------------------------------------------------------
    CATextLayer *pTextLayer1 = [CATextLayer layer];
    pTextLayer1.frame = pNSPanel.frame;
    
    pTextLayer1.string = pNsAttStr; //文本
    //pTextLayer.alignmentMode = kCAAlignmentCenter; //居中
    //pTextLayer.foregroundColor = [NSColor blackColor].CGColor; //设置颜色
    //pTextLayer.fontSize = 30; //字体大小
    //pTextLayer.contentsScale = 2.0;
    

    
    [pView.layer addSublayer: pTextLayer1];
     */
    
    //关闭屏幕水印
    //[pNSPanel close];
    
    return NSApplicationMain(argc, argv);
}