12

我在后台应用程序中遇到了一些问题,该应用程序使用 LSUIElement=1 隐藏其停靠项、菜单栏并防止它出现在 Command-Tab 应用程序切换器中。

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

应用程序在菜单栏中放置一个 NSStatusItem 并在单击时弹出一个菜单。选择“首选项...”应该会弹出一个带有首选项的 NSWindow。

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

我试图通过调用来解决这个问题

[[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];
}

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

这工作,有点,窗口被带到所有应用程序的所有其他窗口顶部的前面,但大多数时候它是不活动的,这意味着它的标题栏是灰色的。单击标题栏也不会使窗口处于活动状态。单击窗口的内部将使其处于活动状态!?

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

在 Snow Leopard 中,有一个新的 API 旨在替换 LSUIElement 以模拟其行为:

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

我已经玩过了,但它只是 SL,我无法设置 LSUIElement。

4

2 回答 2

8

奇怪了——我在Snow Leopard下写一个LSUIElement应用,并没有你描述的这种问题……我确实有新创建的窗口没有出现在最前面的问题,但是我通过调用 activateIgnoringOtherApps 修复它。这就是我必须做的一切才能使其正常工作:

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

我什至没有碰任何名字里有“政策”的东西。

于 2010-11-02T19:49:46.497 回答
4

在绝望地发布问题后,我确实继续寻找并最终找到了解决方案。由于这让我困扰了几天,而且谷歌似乎没有其他答案可以找到,我将解释“未来几代人”的解决方案。

Snow Leopard 添加了一个新的 NSApplicationpresentationOptions 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];

}

我希望有人会发现这很有用。

于 2010-05-28T14:10:34.043 回答