Mac应用状态栏图标右键点击事件捕获方法咨询
如何处理Mac状态栏图标的右键点击事件
我正在开发一款带有状态栏图标的Mac应用,希望处理该图标的右键点击事件。现有实现代码如下:
class StatusBar { var statusBar: NSStatusBar! var statusBarItem: NSStatusItem! init() { statusBar = NSStatusBar() statusBarItem = statusBar.statusItem( withLength: NSStatusItem.variableLength ) if let button = statusBarItem.button { // 图标设置代码省略 // 不生效 button.sendAction(on: .any) button.action = #selector(handleTwoFingerTap(_:)) button.target = self } } @objc private func handleTwoFingerTap(_: Any?) { // 该函数未被调用 } }
当前设置的事件响应未生效,根据Apple官方文档说明:
The only conditions that are actually checked are associated with the NSLeftMouseDownMask, NSLeftMouseUpMask, NSLeftMouseDraggedMask, and NSPeriodicMask bits.
请问该如何正确实现状态栏图标的右键点击事件处理?
方案一:绑定右键弹出菜单(符合macOS交互规范)
这是状态栏应用的标准做法,右键点击直接弹出菜单,实现简单且贴合用户预期:
class StatusBar { var statusBar: NSStatusBar! var statusBarItem: NSStatusItem! private let statusMenu = NSMenu() init() { statusBar = NSStatusBar() statusBarItem = statusBar.statusItem(withLength: NSStatusItem.variableLength) if let button = statusBarItem.button { // 设置图标代码省略 } // 配置菜单选项 statusMenu.addItem(NSMenuItem(title: "功能选项1", action: #selector(menuItem1Tapped), keyEquivalent: "")) statusMenu.addItem(NSMenuItem(title: "功能选项2", action: #selector(menuItem2Tapped), keyEquivalent: "")) statusMenu.addItem(NSMenuItem.separator()) statusMenu.addItem(NSMenuItem(title: "退出应用", action: #selector(quitApplication), keyEquivalent: "")) // 绑定菜单到状态栏项,右键点击自动触发弹出 statusBarItem.menu = statusMenu } @objc private func menuItem1Tapped() { // 处理选项1逻辑 } @objc private func menuItem2Tapped() { // 处理选项2逻辑 } @objc private func quitApplication() { NSApplication.shared.terminate(nil) } }
方案二:单独监听右键点击事件(无菜单)
如果需要执行自定义逻辑而不弹出菜单,可以通过全局事件监测实现:
class StatusBar { var statusBar: NSStatusBar! var statusBarItem: NSStatusItem! private var eventMonitor: EventMonitor? init() { statusBar = NSStatusBar() statusBarItem = statusBar.statusItem(withLength: NSStatusItem.variableLength) if let button = statusBarItem.button { // 设置图标代码省略 } // 监听右键按下事件 eventMonitor = EventMonitor(mask: .rightMouseDown) { [weak self] event in guard let self = self else { return } // 判断点击位置是否在状态栏按钮范围内 if let button = self.statusBarItem.button, button.frame.contains(NSEvent.mouseLocation) { self.handleRightClick() } } eventMonitor?.start() } @objc private func handleRightClick() { // 自定义右键点击逻辑 print("状态栏图标被右键点击") } } // 自定义事件监测工具类 class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask private let handler: (NSEvent?) -> Void init(mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { self.mask = mask self.handler = handler } deinit { stop() } func start() { monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) } func stop() { if let monitor = monitor { NSEvent.removeMonitor(monitor) self.monitor = nil } } }
原代码失效原因
正如官方文档所述,NSStatusBarButton的sendAction(on:)仅对左键相关事件掩码(如NSLeftMouseDownMask)生效,右键点击事件不会触发设置的action,因此必须使用上述两种方案处理。
内容的提问来源于stack exchange,提问作者laike9m
相关产品推荐
相关产品推荐

