如何通知我的 Cocoa 应用程序 NSScreen 分辨率更改?

jam*_*her 2 cocoa objective-c screen-resolution swift

我正在制作一个带有浮动窗口的 Cocoa 应用程序。浮动窗口应该在主屏幕上居中,大小为主屏幕的 1/4。以下 Swift 是我的应用程序的精髓:

import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    var panel: NSPanel!
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let screenRect:CGRect = NSScreen.main()!.frame
        panel = NSPanel(
            contentRect: NSRect(
                x: screenRect.width/4,
                y: screenRect.height/4,
                width:  screenRect.width/2,
                height: screenRect.height/2
            ),
            styleMask: NSWindowStyleMask.nonactivatingPanel,
            backing: NSBackingStoreType.buffered,
            defer: false
        )
        panel.alphaValue = 0.5
        panel.backgroundColor = NSColor.red
        panel.level = Int(CGWindowLevelForKey(CGWindowLevelKey.maximumWindow))
        panel.orderFront(nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生一个像这样的面板:

正确定位

当主屏幕分辨率发生变化时,就会出现问题。显示这一点的一种方法是转到“系统偏好设置”>“显示”并将分辨率设置为“缩放”和“更多空间”。这样做之后,面板看起来像这样:

分辨率更改后定位不正确

可以看到,更改分辨率后面板位置不对。我希望面板保持其位置:居中且屏幕大小的 1/4。为此,我要检测屏幕分辨率(即 的frame属性NSScreen)何时发生变化,以便我可以更改面板的大小和位置。

frame属性发生NSScreen变化时是否会触发某些事件?或者有没有不同的方法来处理这个问题?

jam*_*her 5

在@Adolfo 的帮助下,这有效:

import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    var panel: NSPanel!

    func getPanelRect() -> NSRect {
        let screenRect:CGRect = NSScreen.main()!.frame
        return NSRect(
            x: screenRect.width/4,
            y: screenRect.height/4,
            width:  screenRect.width/2,
            height: screenRect.height/2
        )
    }

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        panel = NSPanel(
            contentRect: self.getPanelRect(),
            styleMask: NSWindowStyleMask.nonactivatingPanel,
            backing: NSBackingStoreType.buffered,
            defer: false
        )
        panel.alphaValue = 0.5
        panel.backgroundColor = NSColor.red
        panel.level = Int(CGWindowLevelForKey(CGWindowLevelKey.maximumWindow))
        panel.orderFront(nil)

        NotificationCenter.default.addObserver(
            forName: NSNotification.Name.NSApplicationDidChangeScreenParameters,
            object: NSApplication.shared(),
            queue: OperationQueue.main
        ) { notification -> Void in
            print("screen parameters changed")
            self.panel.setFrame(self.getPanelRect(), display: true)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)