xcode 显示模态 NSWindow,而不激活其他应用程序窗口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4484521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 20:01:54  来源:igfitidea点击:

Showing a modal NSWindow, without activating the other application windows

cocoaxcodemacosmodal-dialognswindow

提问by Craig Otis

I have an NSStatusItemthat is properly displaying in the MenuBar. One of the items (when clicked) displays a modal NSWindow from my application, which is meant to perform a one-off task, then disappear. (Eg. the user enters a small bit of text, clicks "Save", and the modal NSWindow goes away.)

我有一个NSStatusItem在菜单栏中正确显示的。其中一项(单击时)从我的应用程序中显示一个模式 NSWindow,用于执行一次性任务,然后消失。(例如,用户输入一小段文本,单击“保存”,模式 NSWindow 消失。)

The issue occurs when the application is running in the background. The modal window properly appears above whatever application is running in the foreground, but when the user clicks the "Save" button, the rest of the application's windows also are made active. This is undesirable, as the user then has to click back to whatever app they were using. (Destroying the convenience of the NSStatusItem.) I'm displaying the modal window using:

当应用程序在后台运行时会出现此问题。模态窗口正确显示在前台正在运行的任何应用程序上方,但是当用户单击“保存”按钮时,应用程序的其余窗口也会被激活。这是不可取的,因为用户必须单击返回他们正在使用的任何应用程序。(破坏了 NSStatusItem 的便利性。)我正在使用以下方式显示模式窗口:

[myWindow setFrame:finalRect display:YES animate:NO];
[myWindow setLevel:NSPopUpMenuWindowLevel];
[NSApp runModalForWindow:myWindow];

Is there any way to prevent clicks/events in my popup window from causing the rest of the application to become active? Or a way to let NSApp know that this particular panel shouldn't automatically activate the rest of the app? Thanks!

有什么方法可以防止我的弹出窗口中的点击/事件导致应用程序的其余部分变为活动状态?或者让 NSApp 知道这个特定面板不应该自动激活应用程序的其余部分的方法?谢谢!

回答by Adam Preble

Instead of creating an NSWindow, create an NSPanelwith the style NSNonactivatingPanelMask. You can then do the usual makeKeyAndOrderFront:and orderOut:to show/hide panel as needed.

不是创建NSWindow,而是创建NSPanel具有样式的NSNonactivatingPanelMask。然后,您可以执行通常的操作makeKeyAndOrderFront:orderOut:根据需要显示/隐藏面板。

回答by mralex

A solution by Ken Thomases on the cocoa-dev list a couple years ago looks applicable here too:

几年前,Ken Thomases 在 cocoa-dev 列表中提出的解决方案看起来也适用于这里:

[[NSApplication sharedApplication] hide:self];
[[NSApplication sharedApplication] performSelector:@selector(unhideWithoutActivation) 
                                        withObject:nil 
                                        afterDelay:0.05];

Which in theory tells the application to hide itself and unhide at the bottom of the window stack.

这在理论上告诉应用程序隐藏自己并在窗口堆栈的底部取消隐藏。

You could also intercept the mouse click event and use [NSApp preventWindowOrdering]

您还可以拦截鼠标单击事件并使用 [NSApp preventWindowOrdering]

回答by cSquirrel

NSApp's beginModalSessionForWindow, runModalSession, endModalSession are methods you need.

NSApp 的 beginModalSessionForWindow、runModalSession、endModalSession 是你需要的方法。

Have a look here for example how to use it: Creating a fully customized NSAlert

看看这里的例子如何使用它: 创建一个完全定制的 NSAlert

回答by Bruno Berisso

You can try something like:

您可以尝试以下操作:

...
if ([NSApp isHidden])
    [myWindow makeKeyAndOrderFront:self];
else
    [NSApp runModalForWindow:myWindow];
... 

and when finish:

当完成时:

...
if ([NSApp isHidden])
    [myWindow orderOut:self];
else
    [NSApp stopModal];
...