以编程方式创建的窗口居中

发布于 2024-11-01 20:15:48 字数 678 浏览 3 评论 0原文

我一直在使用这里的示例来创建自定义无标题栏窗口:

在 Mac OS X 上绘制自定义窗口

我发现这是在 Leopard、Snow Leopard 和 Lion 中创建无标题栏窗口的唯一方法,其他方法则不然无论是 Leopard 还是 Lion,都可以正常工作。 (如果我尝试通过普通的 NSWindow 和 IB 调用无标题栏窗口,它将不再在 Leopard 中启动)

到目前为止,这个自定义的无标题栏窗口在任何地方都可以正常工作,但我无法将其居中,只能将其置于硬状态。 Interface Builder 中的固定位置。

使用 [window center] 将普通 NSWindow *window 实现居中是相当容易的,但我发现没有任何东西可以在这个自定义窗口子类上工作,该窗口不是通过 Interface Builder 从 nib 创建的。

我已经尝试了 NSWindow 中的一些操作,但似乎没有任何效果。

有什么想法吗?

I've been using the example from here to create a custom titlebar-less window:

Drawing a custom window on Mac OS X

I've found this is the only way i can create a titlebar-less window in Leopard, Snow Leopard and Lion, other methods don't work right either on Leopard or Lion.
(If i try to invoke a titlebar-less window via normal NSWindow and IB, it won't start up in Leopard anymore)

So far this custom titlebar-less window works great everywhere, but i can't center it, only a hard fixed position in Interface Builder.

It's fairly easy to center a normal NSWindow *window implementation with [window center], but i've found nothing that works on this custom window subclass, a window that isn't created from nib via Interface Builder.

I've tried a few things from NSWindow, but nothing seems to work.

Any Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

≈。彩虹 2024-11-08 20:15:48
CGFloat xPos = NSWidth([[window screen] frame])/2 - NSWidth([window frame])/2;
CGFloat yPos = NSHeight([[window screen] frame])/2 - NSHeight([window frame])/2;
[window setFrame:NSMakeRect(xPos, yPos, NSWidth([window frame]), NSHeight([window frame])) display:YES];

这会将其放置在屏幕的正中央,而不考虑停靠栏和菜单栏占用的空间。如果您想这样做,请将 [[window screen]frame] 更改为 [[window screen]visibleFrame]

CGFloat xPos = NSWidth([[window screen] frame])/2 - NSWidth([window frame])/2;
CGFloat yPos = NSHeight([[window screen] frame])/2 - NSHeight([window frame])/2;
[window setFrame:NSMakeRect(xPos, yPos, NSWidth([window frame]), NSHeight([window frame])) display:YES];

This puts it at the literal center of the screen, not taking into account the space occupied by the dock and menu bar. If you want to do that, change [[window screen] frame] to [[window screen] visibleFrame].

心不设防 2024-11-08 20:15:48
extension NSWindow {
    public func setFrameOriginToPositionWindowInCenterOfScreen() {
        if let screenSize = screen?.frame.size {
            self.setFrameOrigin(NSPoint(x: (screenSize.width-frame.size.width)/2, y: (screenSize.height-frame.size.height)/2))
        }
    }
}
extension NSWindow {
    public func setFrameOriginToPositionWindowInCenterOfScreen() {
        if let screenSize = screen?.frame.size {
            self.setFrameOrigin(NSPoint(x: (screenSize.width-frame.size.width)/2, y: (screenSize.height-frame.size.height)/2))
        }
    }
}
简单气质女生网名 2024-11-08 20:15:48

问题可能应该是为什么[window center]不起作用;但假设是这种情况,请使用 NSScreen 获取屏幕坐标,进行数学计算,然后直接将窗口居中。

The question should probably be why [window center] does not work; but assuming that is the case use NSScreen to get the screen coordinates, do the math, and center the window directly.

疯了 2024-11-08 20:15:48

目标 - macOS Catalina 中的 C,版本 10.15.3

更具可读性 @Wekwa 的答案

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSWindow * window = NSApplication.sharedApplication.windows[0];
    CGFloat xPos = NSWidth(window.screen.frame)/2 - NSWidth(window.frame)/2;
    CGFloat yPos = NSHeight(window.screen.frame)/2 - NSHeight(window.frame)/2;
    [window setFrame:NSMakeRect(xPos, yPos, NSWidth(window.frame), NSHeight(window.frame)) display:YES];
}

Objective - C in macOS Catalina , Version 10.15.3

more readable @Wekwa's answer

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSWindow * window = NSApplication.sharedApplication.windows[0];
    CGFloat xPos = NSWidth(window.screen.frame)/2 - NSWidth(window.frame)/2;
    CGFloat yPos = NSHeight(window.screen.frame)/2 - NSHeight(window.frame)/2;
    [window setFrame:NSMakeRect(xPos, yPos, NSWidth(window.frame), NSHeight(window.frame)) display:YES];
}
内心旳酸楚 2024-11-08 20:15:48

针对 Swift 5 进行了更新,

我总是发现使用 screen.frame 将窗口居中会导致窗口感觉好像离屏幕底部太近。这是因为 Dock 大小几乎是状态/菜单栏的 3 倍(分别约为 70-80 像素和 25 像素)。

这会导致窗口看起来就好像它位于屏幕底部较低的位置,因为我们的眼睛不会自动调整状态栏(1 倍大小)和 Dock(约 3 倍大小)的插入)。

出于这个原因,我总是选择使用 screen.visibleFrame,因为它绝对感觉更加居中。 visibleFrame 会考虑状态栏和 Dock 大小,并计算这两个对象之间的框架的中心点。

extension NSWindow {
    
    /// Positions the `NSWindow` at the horizontal-vertical center of the `visibleFrame` (takes Status Bar and Dock sizes into account)
    public func positionCenter() {
        if let screenSize = screen?.visibleFrame.size {
            self.setFrameOrigin(NSPoint(x: (screenSize.width-frame.size.width)/2, y: (screenSize.height-frame.size.height)/2))
        }
    }
    /// Centers the window within the `visibleFrame`, and sizes it with the width-by-height dimensions provided.
    public func setCenterFrame(width: Int, height: Int) {
        if let screenSize = screen?.visibleFrame.size {
            let x = (screenSize.width-frame.size.width)/2
            let y = (screenSize.height-frame.size.height)/2
            self.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
        }
    }
    /// Returns the center x-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
    /// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
    public func xCenter() -> CGFloat {
        if let screenSize = screen?.visibleFrame.size { return (screenSize.width-frame.size.width)/2 }
        if let screenSize = screen?.frame.size { return (screenSize.width-frame.size.width)/2 }
        return CGFloat(0)
    }
    /// Returns the center y-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
    /// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
    public func yCenter() -> CGFloat {
        if let screenSize = screen?.visibleFrame.size { return (screenSize.height-frame.size.height)/2 }
        if let screenSize = screen?.frame.size { return (screenSize.height-frame.size.height)/2 }
        return CGFloat(0)
    }

}

用法

NSWindow

将现有窗口定位到visibleFrame 的中心。

window!.positionCenter()

设置一个新的窗口框架,位于visibleFrame的中心,尺寸为

window!.setCenterFrame(width: 900, height: 600)

NSView,

使用xCenter()yCenter()来获取visibleFrame<的中心xy点/代码>。

let x = self.view.window?.xCenter() ?? CGFloat(0)
let y = self.view.window?.yCenter() ?? CGFloat(0)
self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(900), height: CGFloat(600)), display: true)

函数示例

override func viewDidLoad() {
    super.viewDidLoad()
    initWindowSize(width: 900, height: 600)
}

func initWindowSize(width: Int, height: Int) {
    let x = self.view.window?.xCenter() ?? CGFloat(0)
    let y = self.view.window?.yCenter() ?? CGFloat(0)
    self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
}

Updated for Swift 5

I always found that centering the window with screen.frame resulted in a window that feels as if it were too close to the bottom of the screen. This is due to the Dock size being nearly 3x as large as the Status/Menu Bar (roughly 70-80px vs. 25px, respectively).

This causes the window to appear as if it were positioned lower to the bottom of the screen, as our eyes do not automatically adjust the insets of the Status Bar (1x size) and the Dock (~3x size).

For this reason, I always choose to go to with screen.visibleFrame, as it definitely feels more centered. visibleFrame takes both the Status Bar and Dock sizes into consideration, and calculates the central points for the frame between those two objects.

extension NSWindow {
    
    /// Positions the `NSWindow` at the horizontal-vertical center of the `visibleFrame` (takes Status Bar and Dock sizes into account)
    public func positionCenter() {
        if let screenSize = screen?.visibleFrame.size {
            self.setFrameOrigin(NSPoint(x: (screenSize.width-frame.size.width)/2, y: (screenSize.height-frame.size.height)/2))
        }
    }
    /// Centers the window within the `visibleFrame`, and sizes it with the width-by-height dimensions provided.
    public func setCenterFrame(width: Int, height: Int) {
        if let screenSize = screen?.visibleFrame.size {
            let x = (screenSize.width-frame.size.width)/2
            let y = (screenSize.height-frame.size.height)/2
            self.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
        }
    }
    /// Returns the center x-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
    /// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
    public func xCenter() -> CGFloat {
        if let screenSize = screen?.visibleFrame.size { return (screenSize.width-frame.size.width)/2 }
        if let screenSize = screen?.frame.size { return (screenSize.width-frame.size.width)/2 }
        return CGFloat(0)
    }
    /// Returns the center y-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
    /// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
    public func yCenter() -> CGFloat {
        if let screenSize = screen?.visibleFrame.size { return (screenSize.height-frame.size.height)/2 }
        if let screenSize = screen?.frame.size { return (screenSize.height-frame.size.height)/2 }
        return CGFloat(0)
    }

}

Usage

NSWindow

Positions the existing window to the center of visibleFrame.

window!.positionCenter()

Sets a new window frame, at the center of visibleFrame, with dimensions

window!.setCenterFrame(width: 900, height: 600)

NSView

Using xCenter() and yCenter() to get the central x-y points of the visibleFrame.

let x = self.view.window?.xCenter() ?? CGFloat(0)
let y = self.view.window?.yCenter() ?? CGFloat(0)
self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(900), height: CGFloat(600)), display: true)

Function Example

override func viewDidLoad() {
    super.viewDidLoad()
    initWindowSize(width: 900, height: 600)
}

func initWindowSize(width: Int, height: Int) {
    let x = self.view.window?.xCenter() ?? CGFloat(0)
    let y = self.view.window?.yCenter() ?? CGFloat(0)
    self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
}
止于盛夏 2024-11-08 20:15:48

我偶然发现了同样的问题。对我有用的是在调用 center() 之前将 NSWindow 对象上的 isRestorable 设置为 false

I stumbled on the same issue. What worked for me is to set isRestorable to false on the NSWindow object before calling center().

四叶草在未来唯美盛开 2024-11-08 20:15:48

Swift 版本:可以为其编写一个简单的静态实用函数

static func positionWindowAtCenter(sender: NSWindow?){
        if let window = sender {
            let xPos = NSWidth((window.screen?.frame)!)/2 - NSWidth(window.frame)/2
            let yPos = NSHeight((window.screen?.frame)!)/2 - NSHeight(window.frame)/2
            let frame = NSMakeRect(xPos, yPos, NSWidth(window.frame), NSHeight(window.frame))
            window.setFrame(frame, display: true)
        }
}

Swift version: One can write a simple static utility function for the same

static func positionWindowAtCenter(sender: NSWindow?){
        if let window = sender {
            let xPos = NSWidth((window.screen?.frame)!)/2 - NSWidth(window.frame)/2
            let yPos = NSHeight((window.screen?.frame)!)/2 - NSHeight(window.frame)/2
            let frame = NSMakeRect(xPos, yPos, NSWidth(window.frame), NSHeight(window.frame))
            window.setFrame(frame, display: true)
        }
}
月牙弯弯 2024-11-08 20:15:48

NSWindow 有一个属性 screen,其中有一个属性 visibleFrame。此属性的工作方式类似于 safeArea(不包括菜单栏和停靠栏的屏幕框架)。 NSWindow 扩展有 Swift 代码。

extension NSWindow {
    func centerOnScreen() {
        guard let screen else {
            return
        }
        
        let screenFrame = screen.visibleFrame
        let windowFrame = frame
        
        let xPosition = screenFrame.width / 2 - windowFrame.width / 2
        let yPosition = screenFrame.height / 2 - windowFrame.height / 2
        let origin = NSPoint(x: xPosition, y: yPosition)
        setFrameOrigin(origin)
    }
}

NSWindow has a property screen, which one has a property visibleFrame. This property works like safeArea (a screen frame excluding menu bar and dock). There is Swift code for NSWindow exension.

extension NSWindow {
    func centerOnScreen() {
        guard let screen else {
            return
        }
        
        let screenFrame = screen.visibleFrame
        let windowFrame = frame
        
        let xPosition = screenFrame.width / 2 - windowFrame.width / 2
        let yPosition = screenFrame.height / 2 - windowFrame.height / 2
        let origin = NSPoint(x: xPosition, y: yPosition)
        setFrameOrigin(origin)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文