Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 将LSUIElement转换为前台应用程序_Macos_Cocoa_Lsuielement - Fatal编程技术网

Macos 将LSUIElement转换为前台应用程序

Macos 将LSUIElement转换为前台应用程序,macos,cocoa,lsuielement,Macos,Cocoa,Lsuielement,我有一个必须一直运行的应用程序(如果用户同意) 当用户退出应用程序时,我将前台应用程序转换为LSUIElement(应用程序只有一个菜单栏图标、停靠图标和菜单消失) 我在菜单项中有一个选项,可以正常工作并将LSUIElement转换为前台应用程序(我使用函数[NSApp setActivationPolicy:NSApp ActivationPolicyRegular]和[NSApp activateIgnoringOtherApps:YES]) 我的问题出现在用户双击应用程序时。我在委托方法应

我有一个必须一直运行的应用程序(如果用户同意)

当用户退出应用程序时,我将前台应用程序转换为LSUIElement(应用程序只有一个菜单栏图标、停靠图标和菜单消失)

我在菜单项中有一个选项,可以正常工作并将LSUIElement转换为前台应用程序(我使用函数
[NSApp setActivationPolicy:NSApp ActivationPolicyRegular]
[NSApp activateIgnoringOtherApps:YES]

我的问题出现在用户双击应用程序时。我在委托方法
应用程序willunhide:(NSNotification*)通知中再次使用
[NSApp setActivationPolicy:nsapplication activationpolicy regular]
,除未显示的菜单外,所有功能都很好。如果我转到另一个应用程序,然后我回来,菜单就会出现。我尝试了不同的方法,但没有找到好的


我想知道的是当用户双击应用程序时调用的委托方法,或者是在那一刻调用的
NSApplication
中的函数是什么,因为我认为在
应用程序中使用
设置激活策略:
将隐藏
函数太晚了。

要将普通应用程序转换为我使用的LSUIElement

ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
并将其更改回前台:

ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToForegroundApplication);

要将普通应用程序转换为LSUIElement,我使用

ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
并将其更改回前台:

ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToForegroundApplication);

答案是这样的。在我找到这个问题之前,我已经做了隐藏/显示。这个问题启发了我最终的答案

下面是以下代码的作用:

  • 当应用程序启动时,应用程序将显示在dock中,并显示菜单栏项
  • 当用户单击菜单栏项时,应用程序将隐藏并从dock中删除
  • 当用户再次单击时,应用程序将显示回dock
  • 如果应用程序被隐藏,并且用户通过双击或启动板再次打开应用程序,则应用程序将在dock中再次显示
  • 如果应用程序未被隐藏,但被其他应用程序遮挡,单击菜单栏项目或重新启动它将使应用程序位于最前面
  • 当用户单击窗口上的关闭按钮时,应用程序将从dock中删除
  • 当用户通过cmd+q或从文件菜单退出应用程序时,应用程序退出,菜单栏项也退出
  • 我已经删除了其他不直接相关的代码

    您可能会注意到的其他事项:

  • 没有为my Info.plist设置LSUIElement或将其设置为NO。如果要设置为“是”。您需要在序列图像板中设置“不启动视图控制器”,并自己从窗口控制器构造
  • 您还需要通过鼠标左键单击菜单栏项来处理逻辑,因为您从一开始就没有窗口
  • 代码:

    import Cocoa
    
    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {
        private let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
        weak private var window:NSWindow? = nil
    
        func applicationDidFinishLaunching(_ aNotification: Notification) {        
            setupMenubarTray()
    
            self.window = NSApp.orderedWindows.first
    
            NotificationCenter.default.addObserver(self, selector: #selector(windowWillClose(_:)), name: NSWindow.willCloseNotification, object: self.window!)
        }
    
        func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
            if !window!.isVisible {
                activeApp()
                return false
            }
    
            return true
        }
    }
    
    extension AppDelegate {
        @objc func windowWillClose(_ noti:Notification) {
            removeFromDock()
        }
    
        private func showInDock() {
            NSApp.setActivationPolicy(.regular)
        }
    
        private func removeFromDock() {
            NSApp.setActivationPolicy(.accessory)
        }
    }
    
    // MARK: - setup menubar button
    extension AppDelegate {
        private func setupMenubarTray() {
            guard let button = statusItem.button else {
                fatalError()
            }
    
            setTrayIcon(for:button)
            button.action = #selector(mouseLeftButtonClicked)
        }
    
        private func setTrayIcon(for button:NSStatusBarButton) {
            let useMonochromeIcon = UserDefaults.standard.bool(forKey: DefaultsKey.useMonochromeIcon.key)
            button.image = NSImage(imageLiteralResourceName: useMonochromeIcon ? "MonochromeIcon" : "TrayIcon")
        }
    
        @objc private func mouseLeftButtonClicked() {
            if NSApp.isHidden || !window!.isKeyWindow {
                self.activeApp()
            } else {
                self.hide()
            }
        }
    
        private func activeApp() {
            showInDock()
            window?.makeKeyAndOrderFront(nil)
            NSApp.activate(ignoringOtherApps: true)
    
            checker.sendNotification()
        }
    
        private func hide() {
            removeFromDock()
            NSApp.hide(nil)
        }
    }
    

    答案是这样的。在我找到这个问题之前,我已经做了隐藏/显示。这个问题启发了我最终的答案

    下面是以下代码的作用:

  • 当应用程序启动时,应用程序将显示在dock中,并显示菜单栏项
  • 当用户单击菜单栏项时,应用程序将隐藏并从dock中删除
  • 当用户再次单击时,应用程序将显示回dock
  • 如果应用程序被隐藏,并且用户通过双击或启动板再次打开应用程序,则应用程序将在dock中再次显示
  • 如果应用程序未被隐藏,但被其他应用程序遮挡,单击菜单栏项目或重新启动它将使应用程序位于最前面
  • 当用户单击窗口上的关闭按钮时,应用程序将从dock中删除
  • 当用户通过cmd+q或从文件菜单退出应用程序时,应用程序退出,菜单栏项也退出
  • 我已经删除了其他不直接相关的代码

    您可能会注意到的其他事项:

  • 没有为my Info.plist设置LSUIElement或将其设置为NO。如果要设置为“是”。您需要在序列图像板中设置“不启动视图控制器”,并自己从窗口控制器构造
  • 您还需要通过鼠标左键单击菜单栏项来处理逻辑,因为您从一开始就没有窗口
  • 代码:

    import Cocoa
    
    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {
        private let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
        weak private var window:NSWindow? = nil
    
        func applicationDidFinishLaunching(_ aNotification: Notification) {        
            setupMenubarTray()
    
            self.window = NSApp.orderedWindows.first
    
            NotificationCenter.default.addObserver(self, selector: #selector(windowWillClose(_:)), name: NSWindow.willCloseNotification, object: self.window!)
        }
    
        func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
            if !window!.isVisible {
                activeApp()
                return false
            }
    
            return true
        }
    }
    
    extension AppDelegate {
        @objc func windowWillClose(_ noti:Notification) {
            removeFromDock()
        }
    
        private func showInDock() {
            NSApp.setActivationPolicy(.regular)
        }
    
        private func removeFromDock() {
            NSApp.setActivationPolicy(.accessory)
        }
    }
    
    // MARK: - setup menubar button
    extension AppDelegate {
        private func setupMenubarTray() {
            guard let button = statusItem.button else {
                fatalError()
            }
    
            setTrayIcon(for:button)
            button.action = #selector(mouseLeftButtonClicked)
        }
    
        private func setTrayIcon(for button:NSStatusBarButton) {
            let useMonochromeIcon = UserDefaults.standard.bool(forKey: DefaultsKey.useMonochromeIcon.key)
            button.image = NSImage(imageLiteralResourceName: useMonochromeIcon ? "MonochromeIcon" : "TrayIcon")
        }
    
        @objc private func mouseLeftButtonClicked() {
            if NSApp.isHidden || !window!.isKeyWindow {
                self.activeApp()
            } else {
                self.hide()
            }
        }
    
        private func activeApp() {
            showInDock()
            window?.makeKeyAndOrderFront(nil)
            NSApp.activate(ignoringOtherApps: true)
    
            checker.sendNotification()
        }
    
        private func hide() {
            removeFromDock()
            NSApp.hide(nil)
        }
    }
    

    从我所知的
    TransformProcessType
    NSApp setActivationPolicy:
    具有相同的效果。从我所知的
    TransformProcessType
    NSApp setActivationPolicy:
    具有相同的效果。您是否尝试过从
    应用程序Houldhandlereopen:
    调用它?是的,我尝试过,但是没有成功。在应用程序隐藏中?我也有同样的问题。您找到解决方案了吗?您是否尝试过从
    应用程序Houldhandlereopen:
    调用它?是的,我尝试过,但没有成功。在applicationDidUnhide中,我也遇到了同样的问题。你找到解决办法了吗?