MacOS 开发 — NSWindow的使用

时间:2024-03-23 14:17:55


零:整体结构

窗口对象包括titleBar,contentView内容视图,contentBoder底部边框区。

titleBar上面包括控制按钮,标题。

MacOS 开发 — NSWindow的使用


一、contentView 相关

1、设置窗口背景颜色

方法1:window.backgroundColor

- (void)setWindowBKColor {
    [self.window setOpaque:NO];
    [self.window setBackgroundColor:[NSColor cyanColor]];
}

    方法2:window.contentView.layer.backgroundColor

        self.window.contentView.layer.backgroundColor = [NSColor cyanColor].CGColor;
        self.window.contentView.wantsLayer = YES;
    

      如果 同时设置上述两种方法,窗口显示为红色,不论设置顺序。

      self.window.contentView.layer.backgroundColor = [NSColor redColor].CGColor;
      self.window.contentView.wantsLayer = YES;
      

      self.window.backgroundColor = [NSColor cyanColor];


        2、设置 window frame/尺寸

            [self.window setContentSize:NSMakeSize(infoWindowW, windowHeight)];
        
        NSRect wndFrame = self.window.frame;
        [self.window setFrame:NSMakeRect(wndFrame.origin.x, wndFrame.origin.y, infoWindowW, windowHeight) display:YES animate:YES];
        self.window.maxSize = NSMakeSize(infoWindowW, windowHeight);
        self.window.minSize = NSMakeSize(infoWindowW, windowHeight);
        

        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7


        3、设置为点击背景可以移动窗口

        • 如果隐藏了标题栏,点击标题栏位置,仍然可以拖动窗口。但是用户不知道标题栏的位置,所以需要设置点击背景也可以移动。

        [self.window setMovableByWindowBackground:YES];


        二、Content Border

        默认是none 不显示出来.
        需要显示的话可以选择 Small/Large Bottom Border 其他选项
        这里我还不知道怎么用代码控制,会的可以告诉我。

        MacOS 开发 — NSWindow的使用


        三、titleBar

        1、设置窗口标题

        [self.window setTitle:@"我的 App 标题"];


        2、设置标题栏图标

        先将 png 格式图片拖到Assets 中,我的图片名为’swift.png’
        配置代码如下:

        self.window.representedURL = [NSURL URLWithString:@"https://www.baidu.com"];  //
            NSImage *image = [NSImage imageNamed:@"swift"];
            [[self.window standardWindowButton:NSWindowDocumentIconButton] setImage:image];
        

          3、隐藏titlebar

          方法1:xib上设置

          选中window,取消勾选titleBar。
          代码中可以通过 window.hasTitleBar 来了解titleBar是否存在,但是 hasTitleBar 属性为只读,所以不能通过代码设置 hasTitleBar。

          MacOS 开发 — NSWindow的使用

          添加颜色看看效果
          连左上角 关闭、放大等选项也消失
          MacOS 开发 — NSWindow的使用


          方法2:代码设置

          self.window.titlebarAppearsTransparent=YES;
          self.window.titleVisibility = NSWindowTitleHidden;
          

            MacOS 开发 — NSWindow的使用

            设置window.contentView 的颜色后,显示效果如下:

            • 可以看到关闭、放大选项,titleBar 只是被隐藏,不代表不存在。

            MacOS 开发 — NSWindow的使用


            4、titleBar和 contentView 融合到一起

            xib:在Main.storyboard选中Window,勾选属性Full Size Content View

            代码:
            self.window.styleMask = self.window.styleMask | NSWindowStyleMaskFullSizeContentView;

            • 不隐藏titleBar

            MacOS 开发 — NSWindow的使用

            • 隐藏titleBar

            MacOS 开发 — NSWindow的使用


            5、自定义titleBar

            参考 tongwei117:mac 自定义titlebar
            https://blog.csdn.net/tongwei117/article/details/71480693

            我的 demo 地址:https://gitee.com/melissashu/MacCustomTitleBar


            原理:隐藏系统自带的titlebar, 继承NSView自己绘制一个titlebar, 在其上添加相应的关闭,最小化,最大化按钮,可以自定义调节颜色,隐藏,显示,高度,以及添加相应的其它控件。

            核心代码:

             self.window.titlebarAppearsTransparent = YES;
                self.window.titleVisibility = NSWindowTitleHidden;
                [self.window setStyleMask:[self.window styleMask] | NSWindowStyleMaskFullSizeContentView];  
            
            self.window.contentViewController = [[MSCBViewController alloc]init];
            

            需要在 MSCBViewController 上添加 customView 和 相应的关闭等按钮。


            如果不指定 window.contentViewController,而是直接使用 contentView 添加,左上角按钮还会存在。

            NSView *msTitleBar = [[NSView alloc]initWithFrame:NSMakeRect(0, titleBarY, self.window.frame.size.width, titleBarH)];
            

            msTitleBar.wantsLayer = YES; //需要先设置这个,再设置颜色,否则颜色无效
            msTitleBar.layer.backgroundColor = [NSColor redColor].CGColor;
            [self.window.contentView addSubview:msTitleBar];

              [[self.window standardWindowButton:NSWindowCloseButton] setEnabled:NO];


              其他可能被隐藏的标准按钮包括:

               enum {
                  NSWindowCloseButton,
                  NSWindowMiniaturizeButton,
                  NSWindowZoomButton,
                  NSWindowToolbarButton,
                  NSWindowDocumentIconButton
               };
              

                四、常用属性、系统样式

                常用的创建代码:

              NSRect frame = CGRectMake(0, 0, 200, 200);
              NSUInteger style =  NSTitledWindowMask | NSClosableWindowMask |NSMiniaturizableWindowMask | NSResizableWindowMask;
              NSWindow *window = [NSWindow alloc]initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:YES];
              window.title = @"New Create Window";
              [window makeKeyAndOrderFront:self];
              

                1、styleMask: 按位表示的窗口风格参数

                enum {
                   NSBorderlessWindowMask = 0, //没有顶部titilebar边框
                   NSTitledWindowMask = 1 << 0, //有顶部titilebar边框
                   NSClosableWindowMask = 1 << 1,//带有关闭按钮
                   NSMiniaturizableWindowMask = 1 << 2,//带有最小化按钮
                   NSResizableWindowMask = 1 << 3,//恢复按钮
                   NSTexturedBackgroundWindowMask = 1 << 8 //带纹理背景的window
                };
                

                2、backing:窗口绘制的缓存模式

                enum {
                   NSBackingStoreRetained       = 0,// 兼容老系统参数,基本很少用到
                   NSBackingStoreNonretained  = 1,//不缓存直接绘制
                   NSBackingStoreBuffered        = 2//缓存绘制
                };
                

                3、defer:表示延迟创建还是立即创建

                4、NSWindowStyleMask

                typedef NS_OPTIONS(NSUInteger, NSWindowStyleMask) {
                    NSWindowStyleMaskBorderless = 0,
                    NSWindowStyleMaskTitled = 1 << 0,//显示标题
                    NSWindowStyleMaskClosable = 1 << 1,//可关闭,如果不加,则关闭按钮处显示一个灰色按钮,不可点击
                    NSWindowStyleMaskMiniaturizable = 1 << 2, //可最小化
                    NSWindowStyleMaskResizable	= 1 << 3,//可调整尺寸,即拉伸
                
                NSWindowStyleMaskTexturedBackground = 1 &lt;&lt; 8,//北京味文字,标题栏没有边框线。如果需要线,要使用 NSUnifiedTitleAndToolbarWindowMask
                
                NSWindowStyleMaskUnifiedTitleAndToolbar = 1 &lt;&lt; 12, //标题栏和toolBar 下有统一的分割线
                
                NSWindowStyleMaskFullScreen NS_ENUM_AVAILABLE_MAC(10_7) = 1 &lt;&lt; 14,//全屏显示
                
                NSWindowStyleMaskFullSizeContentView NS_ENUM_AVAILABLE_MAC(10_10) = 1 &lt;&lt; 15,//contentView会充满整个窗口。
                
                /* 下面样式只适用于NSPanel及其子类 */
                NSWindowStyleMaskUtilityWindow			= 1 &lt;&lt; 4,
                NSWindowStyleMaskDocModalWindow 		= 1 &lt;&lt; 6,
                NSWindowStyleMaskNonactivatingPanel		= 1 &lt;&lt; 7, 
                NSWindowStyleMaskHUDWindow NS_ENUM_AVAILABLE_MAC(10_6) = 1 &lt;&lt; 13 //用于头部显示的panel 
                };
                
                参考博客:https://blog.csdn.net/lovechris00/article/details/77943884


                零:整体结构

                窗口对象包括titleBar,contentView内容视图,contentBoder底部边框区。

                titleBar上面包括控制按钮,标题。

                MacOS 开发 — NSWindow的使用


                一、contentView 相关

                1、设置窗口背景颜色

                方法1:window.backgroundColor

                - (void)setWindowBKColor {
                    [self.window setOpaque:NO];
                    [self.window setBackgroundColor:[NSColor cyanColor]];
                }
                

                  方法2:window.contentView.layer.backgroundColor

                      self.window.contentView.layer.backgroundColor = [NSColor cyanColor].CGColor;
                      self.window.contentView.wantsLayer = YES;
                  

                    如果 同时设置上述两种方法,窗口显示为红色,不论设置顺序。

                    self.window.contentView.layer.backgroundColor = [NSColor redColor].CGColor;
                    self.window.contentView.wantsLayer = YES;