我遇到一个问题,后台应用程序使用LSUIElement = 1隐藏其停靠项,菜单栏并阻止它出现在Command-Tab应用程序切换器中。
这似乎只是Snow Leopard的问题。
应用程序在菜单栏中放置一个NSStatusItem,并在单击时弹出一个菜单。选择“首选项...”应该会显示带有首选项的NSWindow。
首先看起来不起作用的是Window没有在前面排序,但是出现在所有其他应用程序窗口后面。
我试图通过调用
来解决这个问题[[NSApplication sharedApplication] activateIgnoringOtherApps: YES]
但这没效果。
过了一会儿,我发现菜单阻止了发送到运行循环的消息,所以我在MainController上写了另一个方法并发送了延迟信息:
[self performSelector:@selector(setFront :) withObject:[preferencesController window] afterDelay:1.0];
-(void)setFront: (id) theWindow {
[[NSApplication sharedApplication]activateIgnoringOtherApps:YES];
[theWindow orderFrontRegardless];
[theWindow makeKeyWindow];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
请注意send-every-possible-message-to-make-it-do-it-it-it-doing-doing-approach。
这很有效,窗口在所有应用程序的所有其他窗口的顶部显示,但大多数时候它不活动,这意味着它的标题栏显示为灰色。单击标题栏也不会使窗口处于活动状态。单击窗口的INSIDE将使其激活!?
这一切似乎都不是豹子的问题;只是调用activateIgnoringOtherApps并使窗口键似乎工作正常。
在Snow Leopard中有一个新的API,旨在取代应该模仿其行为的LSUIElement:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
我已经玩过了,但它只是SL而且我无法设置LSUIElement。
答案 0 :(得分:8)
这很奇怪 - 我正在Snow Leopard下写一个LSUIElement应用程序,我没有你所描述的问题......我确实遇到了新创建的窗口没有出现在前面的问题,但我通过调用activateIgnoringOtherApps修复了它。这就是我必须做的就是让它按原样运作:
[NSApp activateIgnoringOtherApps: YES];
[preferencesWindow makeKeyAndOrderFront: self];
我甚至没有触及名字中有'政策'的任何东西。
答案 1 :(得分:4)
在绝望中发布问题之后,我确实继续寻找并最终找到了解决方案。由于这让我困扰了几天,谷歌似乎找不到其他答案,我将为“后代”解释解决方案。
Snow Leopard添加了一个新的NSApplication presentationOptions API:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
这应该模拟LSUIElement的工作方式,但提供更多开发人员控制。不幸的是,模拟并不完美,因此10.5和10.6之间的行为发生了变化。
特别是,如果您的应用程序在其info.plist中具有LSUIElement = 1行,则Snow Leopard会将“应用程序的presentationOptions ..”初始化为NSApplicationPresentationOptions标志的等效组合。
只有它不是真的。它将新的NSApplication setActivationPolicy设置为NSApplicationActivationPolicyAccessory:
“应用程序没有出现在Dock中,也没有菜单栏,但可以通过编程方式或通过单击其中一个窗口来激活它。这对应于应用程序的Info.plist中的LSUIElement键的值1。“
尽管提到以编程方式激活,但activateIgnoringOtherApps:完全被忽略了。
解决方案是将激活策略设置为“常规”:
[[NSApplication sharedApplication] setActivationPolicy: NSApplicationActivationPolicyRegular];
当然,如果你使用10.6 SDK作为Base SDK,你只能这样做,这是目前很少有人想做的事情,所以下面是10.5安全的方法:
NSApplication* app = [NSApplication sharedApplication];
if( [app respondsToSelector: @selector(setActivationPolicy:)] ) {
NSMethodSignature* method = [[app class] instanceMethodSignatureForSelector: @selector(setActivationPolicy:)];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: method];
[invocation setTarget: app];
[invocation setSelector: @selector(setActivationPolicy:)];
NSInteger myNSApplicationActivationPolicyAccessory = 0;
[invocation setArgument: &myNSApplicationActivationPolicyAccessory atIndex: 2];
[invocation invoke];
}
我希望有人会觉得这很有用。