NSAlert可以用来创建浮动窗口吗?

发布于 2024-07-17 12:42:36 字数 1433 浏览 5 评论 0原文

我有一个 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 技术交流群。

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

发布评论

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

评论(2

森罗 2024-07-24 12:42:36

不久前,我为这件事伤透了脑筋。

我能让这个工作(某种程度上)的唯一方法是子类化 NSApplication 并覆盖 -sendEvent。 在 -sendEvent 中,你首先调用 super 的实现,然后执行如下操作:

id *modalWindow = [self modalWindow];
if (modalWindow && [modalWindow level] != MY_DESIRED_MODAL_WINDOW_LEVEL)
    [modalWindow setLevel: MY_DESIRED_MODAL_WINDOW_LEVEL];

除此之外,即使这也不能完美地工作 - 当切换应用程序时 - 你无论如何都不想这样做,因为这是一个公然的、粗暴的黑客行为。

所以是的,遗憾的是你最好编写自己的 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:

id *modalWindow = [self modalWindow];
if (modalWindow && [modalWindow level] != MY_DESIRED_MODAL_WINDOW_LEVEL)
    [modalWindow setLevel: MY_DESIRED_MODAL_WINDOW_LEVEL];

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.

帝王念 2024-07-24 12:42:36

我最终所做的就是放弃 NSAlert ,而是从 NIB 加载一个警觉的 NSWindow

下面是显示窗口的代码:

- (void)showAlert {
    NSWindow *w = [self window];
    [w makeFirstResponder:nil];
    [w setLevel:NSFloatingWindowLevel];
    [w center];
    [w makeKeyAndOrderFront:self];
}

其目的是使其像警报一样工作,只不过它也是浮动的,并且不是模态的,因此可以在打开时选择菜单项。

还有什么我应该做的吗?

What I ended up doing was abandoning NSAlert and instead I load an alertish NSWindow from a NIB.

Here is the code that displays the window:

- (void)showAlert {
    NSWindow *w = [self window];
    [w makeFirstResponder:nil];
    [w setLevel:NSFloatingWindowLevel];
    [w center];
    [w makeKeyAndOrderFront:self];
}

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文