2010-05-28 65 views
11

我遇到了一个后台应用程序使用LSUIElement = 1来隐藏它的停靠项目,菜单栏和防止它出现在Command-Tab应用程序切换器中。Snow Leopard&LSUIElement - >应用程序无法正常激活,窗口不是“激活”,尽管是“钥匙”

这似乎是雪豹唯一的问题。

应用程序在菜单栏中放置一个NSStatusItem,并在点击时弹出一个菜单。选择“首选项...”应根据偏好调出NSWindow。

看起来不起作用的第一件事是该窗口没有在前面排序,而是出现在所有其他应用程序窗口的后面。

我试图通过调用

[[NSApplication sharedApplication] activateIgnoringOtherApps: YES] 

解决这一问题,但没有奏效。

一会儿我想出的是,菜单被阻止消息被发送的运行循环,所以我写在MainController的另一种方法,用一个延迟发送的消息后:

[自performSelector:@选择器(setFront :) withObject:[preferencesController window] afterDelay:1.0];

-(void)setFront: (id) theWindow { 

[[NSApplication sharedApplication]activateIgnoringOtherApps:YES]; 
[theWindow orderFrontRegardless]; 
[theWindow makeKeyWindow]; 
     [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; 
} 

请注意发送每一个可能的消息使它做它应该做的方法。

这种方法很有用,窗口在所有应用程序的所有其他窗口的顶端显示,但大多数情况下它不是活动的,这意味着它的标题栏变灰。点击标题栏也不会使窗口处于活动状态。点击窗口的INSIDE将使其激活!?

这一切在Leopard中似乎都不是问题;只是调用activateIgnoringOtherApps并使窗口键似乎工作得很好。

在Snow Leopard中有一个新的API设计,以取代LSUIElement是应该效仿其行为:

http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html

我与周围的发挥,但它的SL-只和我的天堂”没有能够得到LSUIElement被设置。

+0

你想做些什么可以被看作是偷的焦点,这是作出相当困难。这是一件好事。你的菜单做什么? '[preferencesController showWindow:]'? – zneak 2010-05-28 11:56:30

+0

当用户选择“首选项...”并且您将首选项窗口指向前端并将其设置为关键时,它几乎不会窃取焦点,但是苹果公​​司的好人可能会试图阻止您这样做。 – 2010-05-28 13:55:19

回答

4

在无奈之下发布问题后,我确实继续寻找并最终找到解决方案。由于这难以忍受几天,似乎没有其他答案可以在谷歌找到,我会解释为“后代”的解决方案。

雪豹增加了一个新的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是1.”

尽管提的LSUIElement键的值被编程激活,activateIgnoringOtherApps:简直就是完全忽略

的解决方法是激活策略设置。 “普通”:

[[NSApplication sharedApplication] setActivationPolicy: NSApplicationActivationPolicyRegular]; 

当然,你可以,如果你使用10.6 SDK为基地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]; 

} 

我希望有人会觉得这有用。

+0

不幸的是,这有效地将Dock图标带回。 – stephencelis 2011-07-18 01:18:20

+0

是的,它的确如此。无赖 – david 2011-08-01 11:58:39

8

真奇怪 - 我下雪豹写LSUIElement应用程序,并且你所描述我没有这样的问题......我确实有新创建的窗口没有在出现问题前面,但我通过调用activateIgnoringOtherApps来修复它。这就是我必须做的所有事情,以使其工作,因为它应该:

[NSApp activateIgnoringOtherApps: YES]; 
[preferencesWindow makeKeyAndOrderFront: self]; 

我甚至没有触及任何有'政策'的名称。

+0

我想我所经历的是激活政策和其他事物之间的互动。几周前从我的程序中删除了用于选择激活策略的额外代码,但没有不良影响?这是其中的一件事情,不会起作用,然后突然再次开始工作(当然,它可能是OS X点更新之一)。也许我与之合作的窗口不可能成为关键或主要! – 2010-11-03 19:41:40

+0

这对我有效。我有同样的情况。但我的问题是一个小怪物。如果我从XCode运行它,它完美运行。如果我从Finder运行应用程序,窗口不会出现。添加这条线有助于我真的很开心。 – Vojto 2010-12-09 22:47:25

+0

它给了我很多头痛。感谢这个优雅的解决方案 – Tibidabo 2011-10-23 03:31:00