首页 > 解决方案 > 如何创建一个包含仅在按住键盘修改键时出现的 NSMenuItem 的 NSMenu?

问题描述

我想创建一个默认隐藏的NSMenu包含一个NSMenuItem,并且仅在用户按住键盘修饰键时出现。

基本上,我正在寻找与 Finder 的“Go”菜单中的“Library”选项相同的行为:

不持有选项(⌥): 在此处输入图像描述

按住 Option (⌥) 时: 在此处输入图像描述


我已经尝试安装一个关键监听器,通过设置它的属性[NSEvent addGlobalMonitorForEventsMatchingMask: handler:]以编程方式隐藏和取消隐藏它。这种工作,但问题是隐藏/取消隐藏在打开时不起作用。显然,在它打开时完全接管了事件处理循环,从而阻止了关键侦听器工作。 我可能会使用 CGEventTap 在打开时仍然接收事件,但这似乎完全是矫枉过正。NSMenuItemhiddenNSMenuNSMenu
NSMenu

我发现的另一件事与我想要的做类似的事情是NSMenu. 但我只能让它关闭NSMenuItems,而不是隐藏/取消隐藏它们。

任何帮助将不胜感激。谢谢!

标签: macoskeyboard-shortcutshiddennsmenunsmenuitem

解决方案


假设您的仅选项菜单项的操作是(在 Swift 中)performOptionOnlyMenuItem(_:),它的目标是您的AppDelegate.

  • 您需要做的第一件事是确保AppDelegate符合NSMenuItemValidation协议。

  • 您需要做的第二件事是实现该validateMenuItem(_:)方法,并让它检查菜单项是否发送performOptionOnlyMenuItem(_:)操作。如果是这样,请isHidden根据当前是否按下选项键来设置项目的属性。

如果您不需要验证任何其他菜单项,代码可能如下所示:

extension AppDelegate: NSMenuItemValidation {
    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
        switch menuItem.action {
        case #selector(performOptionOnlyMenuItem(_:)):
            let flags = NSApp.currentEvent?.modifierFlags ?? []
            menuItem.isHidden = !flags.contains(.option)
            return true
        default:
            return true
        }
    }
}

如果操作被发送到其他目标,您需要在该目标上实现验证(包括协议一致性)。每个菜单项仅由项目的目标验证。


推荐阅读