【发布时间】:2011-06-12 18:03:06
【问题描述】:
我正在为 Mac OS X 开发一个打字指导应用程序,即使应用程序不在焦点上,也需要将击键转发给它。
有没有办法让系统将击键转发到应用程序,可能通过 NSDistributedNotificationCenter?我用谷歌搜索自己很傻,一直找不到答案......
编辑: 下面的示例代码。
感谢@NSGod 为我指明了正确的方向——我最终使用addGlobalMonitorForEventsMatchingMask:handler: 方法添加了global events monitor,效果很好。为了完整起见,我的实现如下所示:
// register for keys throughout the device...
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
NSString *chars = [[event characters] lowercaseString];
unichar character = [chars characterAtIndex:0];
NSLog(@"keydown globally! Which key? This key: %c", character);
}];
对我来说,棘手的部分是使用块,所以我会给出一些描述以防它帮助任何人:
关于上述代码需要注意的是,它都是对 NSEvent 的单一方法调用。该块作为参数提供,直接到函数。你可以把它想象成一个内联委托方法。只是因为这需要我一段时间才能理解,所以我将在这里一步一步地完成它:
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
这第一位没有问题。您在 NSEvent 上调用一个类方法,并告诉它您要监视哪个事件,在本例中为 NSKeyDownMask。 list of masks for supported event types 可以找到here。
现在,我们来到了棘手的部分:处理程序,它需要一个块:
handler:^(NSEvent *event){
我花了一些编译错误来解决这个问题,但是(感谢 Apple)它们是非常有建设性的错误消息。首先要注意的是克拉^。这标志着区块的开始。之后,在括号内,
NSEvent *event
其中声明了您将在块中用于捕获事件的变量。你可以这样称呼它
NSEvent *someCustomNameForAnEvent
没关系,您只会在块中使用该名称。然后,这就是它的全部内容。确保关闭你的花括号和括号以完成方法调用:
}];
你就完成了!这确实是一种“单线”。在您的应用程序中执行此调用并不重要——我在 AppDelegate 的 applicationDidFinishLaunching 方法中执行此操作。然后,在该块中,您可以从您的应用程序中调用其他方法。
【问题讨论】:
-
嘿 @Pirrpli 非常感谢您为我解释块语法。真的对那些学习有帮助!顺便说一句,效果很好:)
-
没问题。 ;) 当别人为我这样做时,我总是心存感激,所以我会尽力提供帮助。
-
当我尝试这个代码块时,我得到错误:
Incompatible block pointer types sending 'void (^)(struct NSEvent *)'to parameter of type of void (^)(NSEvent *)' in the declaration - @Pirrpli,我忘了添加什么吗?您是否必须包含一些特殊的东西来支持块语法? Screenshot -
我能够通过仔细阅读错误(duh)并从语句中删除“struct”来解决这个问题。
-
请到“系统偏好设置 -> 安全和隐私 -> 隐私 -> 可访问性”检查 Xcode 是否启用,以防它不适用于任何人。
标签: macos keyboard keydown nsnotificationcenter