NSAlert可以用来创建浮动窗口吗?
我有一个 Cocoa 应用程序,它使用 NSAlert 类显示应用程序模式警报。 我希望警报窗口浮动在所有其他应用程序窗口之上。 这可以通过 NSAlert
来完成,还是我需要实现自己的窗口?
我不知道这是否重要,但该应用程序是作为 NSStatusItem
实现的代理应用程序(LSUIElement
为 true)。 (有关该应用程序的更多信息,包括源代码,请查看<此处>。)
以下是显示的代码警报:
- (void)showTimerExpiredAlert {
[NSApp activateIgnoringOtherApps:YES];
NSAlert *alert = [[NSAlert alloc] init];
[alert setAlertStyle:NSInformationalAlertStyle];
[alert setMessageText:NSLocalizedString(@"Menubar Countdown Complete", @"Expiration message")];
[alert setInformativeText:NSLocalizedString(@"The countdown timer has reached 00:00:00.",
@"Expiration information")];
[alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button title")];
[alert addButtonWithTitle:NSLocalizedString(@"Restart Countdown...", @"Restart button title")];
NSInteger clickedButton = [alert runModal];
[alert release];
if (clickedButton == NSAlertSecondButtonReturn) {
// ...
}
}
我尝试将其放在 runModal
调用之前:
[[alert window] setFloatingPanel:YES];
我也尝试过这个:
[[alert window] setLevel:NSFloatingWindowLevel];
但是如果我单击另一个应用程序的窗口,这些窗口都不会使窗口保持在其他窗口之上。 我怀疑 runModal
只是不遵守这些设置。
I have a Cocoa application that displays an application-modal alert using the NSAlert
class. I'd like the alert window to float above all other applications' windows. Can this be done with NSAlert
, or do I need to implement my own window?
I don't know if any of this matters, but the application is an agent application (LSUIElement
is true) implemented as an NSStatusItem
. (For more info about the app, including source code, look <here>.)
Here is the code that displays the alert:
- (void)showTimerExpiredAlert {
[NSApp activateIgnoringOtherApps:YES];
NSAlert *alert = [[NSAlert alloc] init];
[alert setAlertStyle:NSInformationalAlertStyle];
[alert setMessageText:NSLocalizedString(@"Menubar Countdown Complete", @"Expiration message")];
[alert setInformativeText:NSLocalizedString(@"The countdown timer has reached 00:00:00.",
@"Expiration information")];
[alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button title")];
[alert addButtonWithTitle:NSLocalizedString(@"Restart Countdown...", @"Restart button title")];
NSInteger clickedButton = [alert runModal];
[alert release];
if (clickedButton == NSAlertSecondButtonReturn) {
// ...
}
}
I've tried putting this before the runModal
call:
[[alert window] setFloatingPanel:YES];
I've also tried this:
[[alert window] setLevel:NSFloatingWindowLevel];
But neither of those makes the window stay above others if I click another application's window. I suspect runModal
just doesn't honor either of those settings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不久前,我为这件事伤透了脑筋。
我能让这个工作(某种程度上)的唯一方法是子类化 NSApplication 并覆盖 -sendEvent。 在 -sendEvent 中,你首先调用 super 的实现,然后执行如下操作:
除此之外,即使这也不能完美地工作 - 当切换应用程序时 - 你无论如何都不想这样做,因为这是一个公然的、粗暴的黑客行为。
所以是的,遗憾的是你最好编写自己的 NSAlert 版本。 如果您真的关心这种可能性,我会就此提交一个错误。 很奇怪的是 [[alert window] setLevel: someLevel] 没有被 NSApplication 所尊重,并且为了能够做到这一点而不得不重新构建 NSAlert 及其所有简洁的自动布局功能,这是一种浪费。
I wrecked my brain about this exact thing a while ago.
The only way that I could get this to work (sort of), was to subclass NSApplication, and override -sendEvent. In -sendEvent, you'd first call super's implementation, then do something like this:
Apart from that even this didn't work quite spotlessly – when switching apps – you'd never want to do this anyway because it's a blatant, crude hack.
So yes, sadly you're better off writing your own version of NSAlert. If you really care about this possibility, I'd file a bug on it. It is pretty weird that [[alert window] setLevel: someLevel] isn't honored by NSApplication and it's a waste to have to re-build NSAlert with all its neat little auto-layout features just to be able to do this.
我最终所做的就是放弃
NSAlert
,而是从 NIB 加载一个警觉的NSWindow
。下面是显示窗口的代码:
其目的是使其像警报一样工作,只不过它也是浮动的,并且不是模态的,因此可以在打开时选择菜单项。
还有什么我应该做的吗?
What I ended up doing was abandoning
NSAlert
and instead I load an alertishNSWindow
from a NIB.Here is the code that displays the window:
This is intended to make it act like an alert, except that it also floats, and it is not modal, so menu items can be selected while it is up.
Is there anything else I should have done?