Cocoa - 以编程方式转到前台/后台

时间:2012-10-18 06:37:16

标签: xcode macos cocoa

我有一个LSUIElement设置为1的应用程序。它有一个内置编辑器,所以我希望当编辑器打开时应用程序出现在Cmd + Tab循环中。

    -(void)stepIntoForeground
    {
        if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return;
        if (counter == 0) {
            ProcessSerialNumber psn = {0, kCurrentProcess};
            OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToForegroundApplication);
            if (osstatus == 0) {
                ++counter;
            } else {
                //...
            }
        }
    }
    -(void)stepIntoBackground
    {
        if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return;
        if (counter == 0) return;

        if (counter == 1) {
            ProcessSerialNumber psn = {0, kCurrentProcess};
            OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToUIElementApplication);
            if (osstatus == 0) {
                --counter;
            } else {
                //..
            }
        }
    }

问题是:

  • 还有一个Dock图标(不是什么大不了的);
  • 还有菜单,这也不是什么大不了的事,但它们并不总是如此。

有没有办法完全禁用菜单或使其始终显示在前台?提前谢谢。

3 个答案:

答案 0 :(得分:15)

这就是我们这样做的方式。 (作品10.7 +)

  1. 请勿在app plist中使用LSBackgroundOnly NOR LSUIElement
  2. 添加并启动菜单和NSStatusBar菜单
  3. 应用初始化但尚未显示任何窗口后,您可能需要显示第一个窗口(如果有)。我们使用applicationDidFinishLaunching。

    • 如果您不想在应用初始化后使用

      显示任何窗口

      [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

      在10.9上你可以使用其他正确的

      [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

    • 如果你应该在app init完成后打开任何窗口而不是简单地显示主窗口

  4. 维护您的窗口列表

  5. 如果最后一个窗口关闭,请致电

    [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

    在10.9上你可以使用其他正确的

    [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

  6. 下次显示第一个窗口时,请致电

    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    [NSApp activateIgnoringOtherApps:YES];
    [[self window] makeKeyAndOrderFront:nil];

  7. 这应该可以解决问题,如果至少有一个应用程序窗口可见,您将拥有菜单,带有状态信号的停靠图标,以及带有应用程序的cmd + tab元素,如果最后一个应用程序窗口关闭,则仅保留NSStatusBar元素。

    已知问题:

    • 第一步很重要,因为没有它,如果系统模式对话框暂停您的启动(您的应用程序从网上下载并被隔离,可能会在首次启动时出现确认对话框,具体取决于您的安全设置)您的菜单栏在显示第一个应用窗口后,您的应用可能不会拥有该应用。

      解决方法:正常启动应用程序(步骤1)可以解决此问题,但会导致另一个小问题,即使您愿意,您的应用程序图标也可能会在启动时出现在停靠栏中喜欢在没有任何窗口的情况下启动。 (但我们可以解决这个问题,不拥有菜单栏对我们来说是一个更大的问题,所以我们选择了这个问题)

    • 和NSApplicationActivationPolicyRegular之间NSApplicationActivationPolicyAccessory更改(或NSApplicationActivationPolicyProhibited上操作系统波纹管10.9)将杀死状态栏菜单元素的工具提示,工具提示将初步示出,但将NSApplicationActivationPolicyAccessory的第二个呼叫后不永远 - &GT; NSApplicationActivationPolicyProhibited

      解决方法:我们无法为此找到有效的解决方法,并向Apple报告错误。

    • 从NSApplicationActivationPolicyRegular更改为NSApplicationActivationPolicyAccessory在某些操作系统版本上存在其他问题,例如有时在可见应用程序窗口中可能不再有鼠标事件

      解决方法:第一切换到NSApplicationActivationPolicyProhibited(!照顾这导致不期望的应用程序的消息,如NSApplicationWillResignActiveNotification,NSWindowDidResignMainNotification等)

    • 从NSApplicationActivationPolicyAccessory更改为NSApplicationActivationPolicyRegular与某些操作系统版本一样虚假

      • 应用主菜单被冻结,直到第一个应用前端状态发生变化
      • 在此政策之后激活的应用并不总是放在应用程序订单的前面

      解决方法:首先切换到NSApplicationActivationPolicyProhibited,注意最后切换到所需的NSApplicationActivationPolicyRegular应该是mafe延迟,使用f.e. dispatch_async或类似的

答案 1 :(得分:1)

使用swift 4,在applicationDidfinishLaunching(_:Notification)

NSApplication.shared.setActivationPolicy(.regular)

为我做了诀窍,但我只是试图将键盘焦点放到我的编程创建窗口。感谢。

答案 2 :(得分:0)

您可以在plist文件中将App“Application is agent(UIElement)”设置为YES。

修改

我认为有一些黑客可以做到这一点。 但它真的不是它的意思。 Cmd + tab用于将应用程序转到前台,但如果您没有菜单栏,则它看起来不像用户的前景。

我宁愿创建一个菜单栏来访问该应用程序。