美文网首页MacOS 开发收录MAC OSMac优雅使用指南
macOS警告/提示视图 — NSAlert、自定义Window

macOS警告/提示视图 — NSAlert、自定义Window

作者: goyohol | 来源:发表于2021-06-12 05:28 被阅读0次

    系统的NSAlert——系统自带提示视图

    在'ViewController.swift'文件中,先创建一个NSAlert实例来看看~

    import Cocoa
    
    class ViewController: NSViewController {
    
        @objc func clickItem(btn: NSButton) {
            print("clickItem:\(btn.title)")
            
        }
        @objc func showNotice() {
            let alert = NSAlert()
            //添加的前3个项(按钮),会响应‘点击选项时系统的回调’方法——且枚举中有对应项进行确认
            alert .addButton(withTitle: "确定")
            alert .addButton(withTitle: "取消")
            let item3 = alert .addButton(withTitle: "More") //获取对应的按钮
            //item3.target = self; item3.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
            //第4项(按钮)开始,会响应‘点击选项时系统的回调’方法——但枚举中没有对应项进行确认
            let item4 = alert .addButton(withTitle: "第4项")  //获取对应的按钮
            //item4.target = self; item4.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
            let item5 = alert .addButton(withTitle: "第5项")  //获取对应的按钮
            //item5.target = self; item5.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
            alert.messageText = "blabla操作的警告"//标题
            alert.informativeText = "blabla操作会导致XX后果,是否继续?"//详细描述
            //设置NSAlert的展示风格
            alert.alertStyle = NSAlert.Style.critical//warning\informational\critical
            alert .beginSheetModal(for: self.view .window!) { (returnCode: NSApplication.ModalResponse) in
                //点击选项时系统的回调
                switch returnCode {
                case .alertFirstButtonReturn:
                    print("NSApplication.ModalResponse.alertFirstButtonReturn")
                case .alertSecondButtonReturn:
                    print("NSApplication.ModalResponse.alertSecondButtonReturn")
                case .alertThirdButtonReturn:
                    print("NSApplication.ModalResponse.alertThirdButtonReturn")
                //以下条件均不会到达
                case .stop:
                    print("NSApplication.ModalResponse.stop")
                case .abort:
                    print("NSApplication.ModalResponse.abort")
                case .`continue`:
                    print("NSApplication.ModalResponse.`continue`")
                case .OK:
                    print("NSApplication.ModalResponse.OK")
                case .cancel:
                    print("NSApplication.ModalResponse.cancel")
                case .continue:
                    print("NSApplication.ModalResponse.continue")
                default:
                    print("Other situation——default")
                    break
                }
            }
            
        }
        func addOneBtn() {//为该window,随便添加一个按钮
            let btn = NSButton(frame: NSMakeRect(100, 100, 100, 100))
            btn.target = self; btn.action = #selector(showNotice)
            self.view .addSubview(btn)
        }
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            self .addOneBtn()//添加按钮
            
        }
    
        override var representedObject: Any? {
            didSet {
            // Update the view, if already loaded.
            }
        }
    
    
    }
    

    效果:
    1.点击'Button'按钮后弹出NSAlert视图!弹出该NSAlert视图(除了该NSAlert视图 进行选择)其他视图 不能进行操作~
    2.前3项(按钮)——点击第1项('确定')/第2项('取消')/第3项('More')后NSAlert视图会消失并打印NSApplication.ModalResponse.alertFirstButtonReturn/NSApplication.ModalResponse.alertSecondButtonReturn/NSApplication.ModalResponse.alertThirdButtonReturn
    3.从第4项(按钮)开始,点击第4项('第4项')/第5项('第5项')后NSAlert视图会消失并都打印Other situation——default

    结论:添加的前3个项(按钮),会响应‘点击选项时系统的回调’方法——且枚举中有对应项进行确认!第4项(按钮)开始,会响应‘点击选项时系统的回调’方法——但枚举中没有对应项进行确认!

    Tips:可通过open func addButton(withTitle title: String) -> NSButton方法,获取该项对应按钮!对其按钮重写方法覆盖‘点击选项时系统的回调’方法后,点击该项后NSAlert视图不会消失系统默认‘点击选项时系统的回调方法而是执行@objc func clickItem(btn: NSButton)方法)!

    公开注释后的@objc func showNotice()方法:

    @objc func showNotice() {
       let alert = NSAlert()
        //添加的前3个项(按钮),会响应‘点击选项时系统的回调’方法——且枚举中有对应项进行确认
        alert .addButton(withTitle: "确定")
        alert .addButton(withTitle: "取消")
        let item3 = alert .addButton(withTitle: "More") //获取对应的按钮
        item3.target = self; item3.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
        //第4项(按钮)开始,会响应‘点击选项时系统的回调’方法——但枚举中没有对应项进行确认
        let item4 = alert .addButton(withTitle: "第4项")  //获取对应的按钮
        item4.target = self; item4.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
       let item5 = alert .addButton(withTitle: "第5项")  //获取对应的按钮
        item5.target = self; item5.action = #selector(clickItem)//重写方法—覆盖‘点击选项时系统的回调’方法
        alert.messageText = "blabla操作的警告"//标题
        alert.informativeText = "blabla操作会导致XX后果,是否继续?"//详细描述
        //设置NSAlert的展示风格
        alert.alertStyle = NSAlert.Style.critical//warning\informational\critical
        alert .beginSheetModal(for: self.view .window!) { (returnCode: NSApplication.ModalResponse) in
            //点击选项时系统的回调
            switch returnCode {
            case .alertFirstButtonReturn:
                print("NSApplication.ModalResponse.alertFirstButtonReturn")
            case .alertSecondButtonReturn:
                print("NSApplication.ModalResponse.alertSecondButtonReturn")
            case .alertThirdButtonReturn:
                print("NSApplication.ModalResponse.alertThirdButtonReturn")
            //以下条件均不会到达
            case .stop:
                print("NSApplication.ModalResponse.stop")
            case .abort:
                print("NSApplication.ModalResponse.abort")
            case .`continue`:
                print("NSApplication.ModalResponse.`continue`")
            case .OK:
                print("NSApplication.ModalResponse.OK")
            case .cancel:
                print("NSApplication.ModalResponse.cancel")
            case .continue:
                print("NSApplication.ModalResponse.continue")
            default:
                print("Other situation——default")
                break
            }
        }
        
    }
    

    该项对应按钮的点击回调方法:

    @objc func clickItem(btn: NSButton) {
        print("clickItem:\(btn.title)")
        
    }
    

    效果:
    1.点击'Button'按钮后弹出NSAlert视图!弹出该NSAlert视图(除了该NSAlert视图 进行选择)其他视图 不能进行操作~
    2.前2项(按钮)——点击第1项('确定')/第2项('取消')/后NSAlert视图会消失并打印NSApplication.ModalResponse.alertFirstButtonReturn/NSApplication.ModalResponse.alertSecondButtonReturn/NSApplication.ModalResponse.alertThirdButtonReturn
    3.从第3项(按钮)开始—对应按钮添加了action响应,点击第3项('More')/第4项('第4项')/第5项('第5项')后NSAlert视图均不会消失系统默认‘点击选项时系统的回调方法)并执行@objc func clickItem(btn: NSButton)方法后分别打印clickItem:More/clickItem:第4项/clickItem:第5项


    NSAlertalertStyle属性对应的效果——NSAlert.Style.warningNSAlert.Style.informationalNSAlert.Style.critical

    NSAlert.Style.warning NSAlert.Style.informational NSAlert.Style.critical

    由上面代码可以发现NSAlert实例对象是基于NSWindow对象创建的!
    所以代码如下:为NSWindow类添加扩展(extension)~

     extension NSWindow {
        //创建macOS警告/提示视图——返回NSApplication.ModalResponse
        public func showAlertNotice(firstItemStr: String, secondItemStr: String, title: String, information: String, alertStyle: NSAlert.Style, completionHalder handler: @escaping ((NSApplication.ModalResponse) -> Void)) {//@escaping——去除“scaping closure captures non-escaping parameter 'handler'”警告
            let alert = NSAlert()
            alert .addButton(withTitle: firstItemStr)
            alert .addButton(withTitle: secondItemStr)
            alert.messageText = title//标题
            alert.informativeText = information//详细描述
            //设置NSAlert的展示风格
            alert.alertStyle = alertStyle//warning\informational\critical
            alert .beginSheetModal(for: self) { (returnCode: NSApplication.ModalResponse) in
                //点击选项时系统的回调
                handler(returnCode)
            }
        }
        //创建macOS警告/提示视图——返回bool值
        public func showAlertNoticeWithBool(firstItemStr: String, secondItemStr: String, title: String, information: String, alertStyle: NSAlert.Style, completionHalder handler: @escaping ((Bool) -> Void)) {//@escaping——去除“scaping closure captures non-escaping parameter 'handler'”警告
            let alert = NSAlert()
            alert .addButton(withTitle: firstItemStr)
            alert .addButton(withTitle: secondItemStr)
            alert.messageText = title//标题
            alert.informativeText = information//详细描述
            //设置NSAlert的展示风格
            alert.alertStyle = alertStyle//warning\informational\critical
            alert .beginSheetModal(for: self) { (returnCode: NSApplication.ModalResponse) in
                //点击选项时系统的回调
                if returnCode == .alertFirstButtonReturn {//点击"确定"
                    handler(true)
                } else if returnCode == .alertSecondButtonReturn {//点击"取消"
                    handler(false)
                }
            }
            
        }
    }
    

    方法的调用:在'ViewController.swift'文件中

    //返回NSApplication.ModalResponse
    self.view.window! .showAlertNotice(firstItemStr: "OK", secondItemStr: "取消", title: "标题", information: "警告的提示内容和信息", alertStyle: .critical) { (returnCode : NSApplication.ModalResponse) in
        if returnCode == .alertFirstButtonReturn {//点击"确定"
            print("returnCode == .alertFirstButtonReturn")
            //"确定"相应的操作
        } else if returnCode == .alertSecondButtonReturn {//点击"取消"
            print("returnCode == .alertSecondButtonReturn")
            //"取消"相应的操作
        }
    }
    
    //返回bool值
    self.view.window! .showAlertNoticeWithBool(firstItemStr: "OK", secondItemStr: "取消", title: "标题", information: "警告的提示内容和信息", alertStyle: .critical) { (isOK: Bool) in
        if isOK == true {//点击"确定"
            print("isOK == true")
            //"确定"相应的操作
        } else {//点击"取消"
            print("isOK == false")
            //"取消"相应的操作
        }
    }
    



    自定义WindowController

    新建一个自定义的GYHNoticeAlertWindowController类(需勾选'Also create XIB file for user interface'

    勾选'Also create XIB file for user interface'

    添加的图片素材:

    图片素材

    在'GYHNoticeAlertWindowController.swift'文件中,进行控件UI布局

    import Cocoa
    
    class GYHNoticeAlertWindowController: NSWindowController {
        var sureBtn: NSButton!
        var cancelBtn: NSButton!
        
        var _title: String?     //标题
        var _message: String?   //提示信息
        var _okStr: String?     //“确定”文字
        var _cancelStr: String? //“取消”文字
        var _backColor: NSColor?//背景色
        convenience init(title: String?, message: String?, backColor: NSColor?, okStr: String?, cancelStr: String?) {
            self.init(windowNibName: "GYHNoticeAlertWindowController")
            
            _title = title != nil ? title : "警告"
            _message = message != nil ? message : "提示信息的内容:blabla~"
            _okStr = okStr != nil ? okStr : "确定"
            _cancelStr = cancelStr != nil ? cancelStr : "取消"
            _backColor = backColor != nil ? backColor : NSColor(red: 190/255.0, green: 150/255.0, blue: 125/255.0, alpha: 1.0)
        }
        override func windowDidLoad() {
            super.windowDidLoad()
            
            // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
            //对窗口(self.window)进行配置
            self.window?.isRestorable = false//窗口不可拉伸
            self.window?.titlebarAppearsTransparent = true
            self.window?.title = _title!//标题
            self.window?.titleVisibility = NSWindow.TitleVisibility.hidden//隐藏窗口标题
            self.window?.styleMask = NSWindow.StyleMask.fullSizeContentView//窗口风格:顶部视图+窗口(融合)
            self.window?.isMovableByWindowBackground = true//点击背景,可移动
            //设置背景色
            self.window?.contentView?.wantsLayer = true
            self.window?.contentView?.layer?.backgroundColor = _backColor?.cgColor
            //self.window?.contentView?.layer?.cornerRadius = 5.0//无效:切圆角—边框未隐藏
            
            self .setUpAllViews()
            self .setUpTitleBarV()
            
        }
        func setUpAllViews() {  //视图布局——"确定"按钮、"取消"按钮、提示信息Label
            var window_W = self.window?.frame.size.width;
            window_W = window_W != nil ? window_W : 0.0;
            
            let margin_Of_TwoBtns = (200.0/3600.0)*window_W!;
            //"确定"按钮
            let sureBtn_W = (1400.0/3600.0)*window_W!;   let sureBtn_X = window_W!/2.0 - margin_Of_TwoBtns/2.0 - sureBtn_W;
            let sureBtn_H = (360.0/3600.0)*window_W!;    let sureBtn_Y = (150.0/3600.0)*window_W!;
            sureBtn = NSButton(frame: NSMakeRect(sureBtn_X, sureBtn_Y, sureBtn_W, sureBtn_H))
            self.window?.contentView?.addSubview(sureBtn)
            sureBtn.title = _okStr!
            sureBtn.alignment = NSTextAlignment.center
            sureBtn.bezelStyle = .circular
            sureBtn.setButtonType(NSButton.ButtonType.switch)//按钮类型(可多选)
            sureBtn.imagePosition = .imageOverlaps//图片放在最下面
            sureBtn.imageScaling = .scaleAxesIndependently//图片自动调整尺寸
            sureBtn.image = NSImage(named: "Item_Button_nor")//图片——普通状态
            sureBtn.alternateImage = NSImage(named: "Item_Button_sel")//图片——高亮状态
            //"取消"按钮
            let cancelBtn_W = (1400.0/3600.0)*window_W!;   let cancelBtn_X = window_W!/2.0 + margin_Of_TwoBtns/2.0;
            let cancelBtn_H = (360.0/3600.0)*window_W!;    let cancelBtn_Y = (150.0/3600.0)*window_W!;
            cancelBtn = NSButton(frame: NSMakeRect(cancelBtn_X, cancelBtn_Y, cancelBtn_W, cancelBtn_H))
            self.window?.contentView?.addSubview(cancelBtn)
            cancelBtn.title = _cancelStr!
            cancelBtn.alignment = NSTextAlignment.center
            cancelBtn.bezelStyle = .circular
            cancelBtn.setButtonType(NSButton.ButtonType.switch)//按钮类型(可多选)
            cancelBtn.imagePosition = .imageOverlaps//图片放在最下面
            cancelBtn.imageScaling = .scaleAxesIndependently//图片自动调整尺寸
            cancelBtn.image = NSImage(named: "Item_Button_nor")//图片——普通状态
            cancelBtn.alternateImage = NSImage(named: "Item_Button_sel")//图片——高亮状态
            
            //提示信息Label
            let tipLabel_X = 0.0;       let tipLabel_Y = self.sureBtn.frame.maxY + (110.0/2800.0)*window_W!
            let tipLabel_W = window_W!;  let tipLabel_H = (300.0/2800.0)*window_W!
            let tipContentLabel = NSTextField(frame: NSMakeRect(CGFloat(tipLabel_X), tipLabel_Y, tipLabel_W, tipLabel_H))
            self.window?.contentView?.addSubview(tipContentLabel)
            tipContentLabel.isEditable = false//不可编辑
            tipContentLabel.isBordered = false//不显示边框
            tipContentLabel.backgroundColor = .clear
            tipContentLabel.alignment = .center
            tipContentLabel.font = NSFont .boldSystemFont(ofSize: 15.0)
            tipContentLabel.textColor = .lightGray
            tipContentLabel.stringValue = _message!
        }
        func setUpTitleBarV() { //设置窗口的标题栏
            let titleBar_Height: CGFloat = 27.0
            let titleBarImgV = NSImageView()
            self.window?.contentView?.addSubview(titleBarImgV)
            //添加约束
            titleBarImgV.translatesAutoresizingMaskIntoConstraints = false;
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: titleBarImgV, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.window?.contentView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: titleBarImgV, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.window?.contentView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: titleBar_Height))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: titleBarImgV, attribute: NSLayoutConstraint.Attribute.left, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.window?.contentView, attribute: NSLayoutConstraint.Attribute.left, multiplier: 1.0, constant: 0.0))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: titleBarImgV, attribute: NSLayoutConstraint.Attribute.right, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.window?.contentView, attribute: NSLayoutConstraint.Attribute.right, multiplier: 1.0, constant: 0.0))
            titleBarImgV.image = NSImage(named: "titleBar_Img")
            titleBarImgV.imageScaling = NSImageScaling.scaleAxesIndependently//图片自动调整尺寸
            
            let nameLB_leftMargin: CGFloat = 3.0
            let nameLB_Height: CGFloat = 20.0
            let nameLabel = NSTextField()
            self.window?.contentView?.addSubview(nameLabel)
            //添加约束-简写
            nameLabel.translatesAutoresizingMaskIntoConstraints = false
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: nameLabel, attribute: .top, relatedBy: .equal, toItem: self.window?.contentView, attribute: .top, multiplier: 1.0, constant: (titleBar_Height - nameLB_Height)))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: nameLabel, attribute: .bottom, relatedBy: .equal, toItem: self.window?.contentView, attribute: .top, multiplier: 1.0, constant: titleBar_Height))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: nameLabel, attribute: .left, relatedBy: .equal, toItem: self.window?.contentView, attribute: .left, multiplier: 1.0, constant: nameLB_leftMargin))
            self.window?.contentView?.addConstraint(NSLayoutConstraint(item: nameLabel, attribute: .right, relatedBy: .equal, toItem: self.window?.contentView, attribute: .right, multiplier: 1.0, constant: 0.0))
            nameLabel.isBordered = false
            nameLabel.isEditable = false
            nameLabel.backgroundColor = NSColor.clear
            nameLabel.textColor = NSColor.gridColor
            nameLabel.font = NSFont .boldSystemFont(ofSize: 13.0)
            nameLabel.stringValue = _title!//标题
        }
        
    }
    

    在'ViewController.swift'文件中,进行使用:

    import Cocoa
    
    class ViewController: NSViewController, NSWindowDelegate {
        
        var noticeWC: GYHNoticeAlertWindowController?//自定义‘提示’窗口
        //事件的响应——自定义‘提示’窗口
        @objc func clickWindowButton(btn: NSButton) {
            btn.state = NSControl.StateValue.off//改为‘关闭’状态——非选中
            
            if btn == noticeWC?.sureBtn {//点击"确定"
                print("btn == noticeWC?.sureBtn")
                //"确定"相应的操作
                
                //关闭模态、关闭窗口
                NSApplication .shared .stopModal()
                self .dismissNotice()
            } else if btn == noticeWC?.cancelBtn {//点击"取消"
                print("btn == noticeWC?.cancelBtn")
                //"取消"相应的操作
                
                //关闭模态、关闭窗口
                NSApplication .shared .stopModal()
                self .dismissNotice()
            }
        }
        //创建并展示‘提示’窗口
        public func createShowNotice(with delegate: NSWindowDelegate?) {
            //判空,避免重复创建
            noticeWC = noticeWC != nil ? noticeWC : GYHNoticeAlertWindowController(title: nil, message: nil, backColor:nil, okStr: nil, cancelStr: nil)//自定义初始化方法
            noticeWC? .showWindow(nil)
            //if delegate != nil {
            //    noticeWC?.window?.delegate = delegate;
            //} //无需delegate
            noticeWC?.sureBtn?.target = self;   noticeWC?.sureBtn?.action = #selector(clickWindowButton)
            noticeWC?.cancelBtn?.target = self; noticeWC?.cancelBtn?.action = #selector(clickWindowButton)
            
            //开启模态
            NSApplication .shared .runModal(for: (noticeWC?.window)!)
        }
        //隐藏‘提示’窗口
        public func dismissNotice() {
            noticeWC? .close()//关闭窗口
            //noticeWC?.window?.delegate = nil  //无需delegate
            noticeWC = nil//置为nil
        }
        
        @objc func showNotice() {
            self .createShowNotice(with: nil)
        }
    
        func addOneBtn() {//为该window,随便添加一个按钮
            let btn = NSButton(frame: NSMakeRect(100, 100, 100, 100))
            btn.target = self; btn.action = #selector(showNotice)
            self.view .addSubview(btn)
        }
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            self .addOneBtn()//添加按钮
            
        }
            
        override var representedObject: Any? {
            didSet {
            // Update the view, if already loaded.
            }
        }
    
    
    }
    

    效果:
    1.点击'Button'按钮后弹出自定义‘提示’窗口GYHNoticeAlertWindowController窗口)!弹出GYHNoticeAlertWindowController窗口(除了该GYHNoticeAlertWindowController窗口 进行选择)其他视图 不能进行操作~
    2.点击'确定'/'取消'后该GYHNoticeAlertWindowController窗口会消失并进行其相应的打印!之后其他视图 可以进行操作~

    在"Debug View hierarchy"中查看视图层次:

    1.系统默认自带的窗口('NSWindowController'):

    NSWindowController


    2.自定义‘提示’窗口('GYHNoticeAlertWindowController'):

    GYHNoticeAlertWindowController


    思路如此,封装看个人~(不想去封装了😒)


    Tip1:关于按钮字体居中颜色大小,可参考NSButton的使用(Mac端 按钮)》中“设置按钮的标题颜色及字体”部分:
    其中“-(void)setTitleColorToColor:(NSColor *)color andFontNum:(CGFloat)FontNum isBold:(BOOL)isBold;”方法通过了设置按钮的attributedTitle属性(富文本)中使用[paraStyle setAlignment:NSTextAlignmentCenter];实现了字体居中~


    Tip2:关于提示信息Label的文字可能超出控件范围的问题:

    • 1.可以设置其toolTip属性—鼠标放置上去就会展示出来!(效果如下)



    不想再写份Swift的代码~😂

    Tip3:解决“顶部标题栏鼠标不能拖动边框不圆滑”的问题

    self.window?.styleMask = NSWindow.StyleMask.fullSizeContentView//窗口风格:顶部视图+窗口(融合)
    

    替换为如下代码:

    self.window?.styleMask = [self.window!.styleMask, >NSWindow.StyleMask.fullSizeContentView]//窗口风格:圆滑边框、顶部视图+窗口(融合)
    //获取 (系统)左侧的‘关闭’、‘最小化’、‘最大化’按钮
    let closeBtn = self.window?.standardWindowButton(NSWindow.ButtonType.closeButton)
    let zoomBtn = self.window?.standardWindowButton(NSWindow.ButtonType.zoomButton)
    let miniaturizeBtn = self.window?.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)
    closeBtn?.isHidden = true       //隐藏 ‘关闭’按钮     //初始位置 X:7.0   Y:3.0
    zoomBtn?.isHidden = true        //隐藏 ‘最大化’按钮     //初始位置 X:47.0   Y:3.0
    miniaturizeBtn?.isHidden = true //隐藏 ‘最小化’按钮   //初始位置 X:27.0   Y:3.0
    

    优化后效果:顶部标题栏鼠标可以拖动边框圆滑










    goyohol's essay

    相关文章

      网友评论

        本文标题:macOS警告/提示视图 — NSAlert、自定义Window

        本文链接:https://www.haomeiwen.com/subject/omvvpqtx.html