OS X:检测系统范围的 keyDown 事件? [英] OS X: Detect system-wide keyDown events?

查看:29
本文介绍了OS X:检测系统范围的 keyDown 事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发适用于 Mac OS X 的打字辅导应用程序,即使该应用程序不在焦点上,它也需要将击键转发给它.

I'm working on a typing-tutor application for Mac OS X that needs to have keystrokes forwarded to it, even when the application is not in focus.

有没有办法让系统将击键转发到应用程序,可能是通过 NSDistributedNotificationCenter?我在谷歌上搜索了自己的愚蠢,并没有找到答案......

Is there a way to have the system forward keystrokes to the app, possibly through NSDistributedNotificationCenter? I've googled myself silly, and haven't been able to find an answer...

下面的示例代码.

感谢@NSGod 为我指明了正确的方向——我最终添加了一个 全局事件监视器 使用方法 addGlobalMonitorForEventsMatchingMask:handler:,该方法工作得很好.为了完整起见,我的实现如下所示:

Thanks @NSGod for pointing me in the right direction -- I ended up adding a global events monitor using the method addGlobalMonitorForEventsMatchingMask:handler:, which works beautifully. For completeness, my implementation looks like this:

// 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);

}];

对我来说,棘手的部分是使用块,所以我会给出一些描述,以防它对任何人有帮助:

For me, the tricky part was using blocks, so I'll give a little description in case it helps anyone:

关于上述代码需要注意的是,它都是对 NSEvent 的单一方法调用.该块作为参数提供,直接函数.你可以把它想象成一个内联委托方法.仅仅因为这对我来说需要一段时间才能理解,我将在这里一步一步地解决它:

The thing to notice about the above code is that it's all one single method call on NSEvent. The block is supplied as an argument, directly to the function. You could think of it kind of like an inline delegate method. Just because this took a while to sink in for me, I'm going to work through it step by step here:

[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask

这个第一位没问题.您正在 NSEvent 上调用类方法,并告诉它您要监视哪个事件,在本例中为 NSKeyDownMask.支持事件类型的掩码列表可以在这里.

This first bit is no problem. You're calling a class method on NSEvent, and telling it which event you're looking to monitor, in this case NSKeyDownMask. A list of masks for supported event types can be found here.

现在,我们来到棘手的部分:处理程序,它需要一个块:

Now, we come to the tricky part: handler, which expects a block:

handler:^(NSEvent *event){

我花了一些编译错误才把它弄对了,但是(感谢 Apple)它们是非常有建设性的错误消息.首先要注意的是克拉 ^.这标志着块的开始.之后,在括号内,

It took me a few compile errors to get this right, but (thank you Apple) they were very constructive error messages. The first thing to notice is the carat ^. That signals the start of the block. After that, within the parentheses,

NSEvent *event

它声明了您将在块中用于捕获事件的变量.你可以称之为

Which declares the variable that you'll be using within the block to capture the event. You could call it

NSEvent *someCustomNameForAnEvent

没关系,您只需在块中使用该名称即可.然后,这就是它的全部内容.确保关闭大括号和括号以完成方法调用:

doesn't matter, you'll just be using that name within the block. Then, that's just about all there is to it. Make sure to close your curly brace, and bracket to finish the method call:

}];

你完成了!这确实是一种单线".您在应用程序中的何处执行此调用无关紧要——我在 AppDelegate 的 applicationDidFinishLaunching 方法中执行此操作.然后,在块内,您可以从应用内调用其他方法.

And you're done! This really is kind of a 'one-liner'. It doesn't matter where you execute this call within your app -- I do it in the AppDelegate's applicationDidFinishLaunching method. Then, within the block, you can call other methods from within your app.

推荐答案

如果您对 OS X 10.6+ 的最低要求没问题,并且可以只读"访问事件流,则可以安装Cocoa 中的全局事件监视器:Cocoa 事件处理指南:监控事件.

If you are okay with a minimum requirement of OS X 10.6+, and can suffice with "read-only" access to the stream of events, you can install a global event monitor in Cocoa: Cocoa Event-Handling Guide: Monitoring Events.

如果您需要支持 OS X 10.5 及更早版本,并且只读访问是可以的,并且不介意使用 Carbon Event Manager,您基本上可以使用 GetEventMonitorTarget().(不过,您将很难找到有关该方法的任何(官方)文档).我相信,该 API 最早出现在 OS X 10.3 中.

If you need to support OS X 10.5 and earlier, and read-only access is okay, and don't mind working with the Carbon Event Manager, you can basically do the Carbon-equivalent using GetEventMonitorTarget(). (You will be hard-pressed to find any (official) documentation on that method though). That API was first available in OS X 10.3, I believe.

如果您需要对事件流进行读写访问,那么您将需要查看属于 ApplicationServices > CoreGraphics 的一个稍微低级的 API:CGEventTapCreate() 和朋友们.这在 10.4 中首次可用.

If you need read-write access to the event stream, then you will need to look at a slightly lower-level API that is part of ApplicationServices > CoreGraphics:CGEventTapCreate() and friends. This was first available in 10.4.

请注意,所有 3 种方法都要求用户在系统偏好设置">通用访问"偏好设置面板中启用启用辅助设备访问"(至少对于关键事件).

Note that all 3 methods will require that the user have "Enable access for assistive devices" enabled in the System Preferences > Universal Access preference pane (at least for key events).

这篇关于OS X:检测系统范围的 keyDown 事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆