我无法获得启用辅助功能的应用程序(开发案例中的XCode)来捕获全局keyDown事件。我已经看到了很多代码示例,如下所示,但这对我来说不适用于10.9.4。
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
// 10.9+ only, see this url for compatibility:
// http://stackoverflow.com/questions/17693408/enable-access-for-assistive-devices-programmatically-on-10-9
BOOL checkAccessibility()
{
NSDictionary* opts = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts);
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
if (checkAccessibility()) {
NSLog(@"Accessibility Enabled");
}
else {
NSLog(@"Accessibility Disabled");
}
NSLog(@"registering keydown mask");
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
NSLog(@"keydown: %@", event.characters);
}];
NSLog(@"entering run loop.");
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
收到的输出是:
2014-08-25 17:26:36.054 test[64725:303] Accessibility Enabled
2014-08-25 17:26:36.055 test[64725:303] registering keydown mask
2014-08-25 17:26:36.067 test[64725:303] entering run loop.
一旦到了这里,就不会发生其他日志记录,无论我点击哪个键或者点击它时应用程序有什么焦点。
FWIW,我正在尝试写一个辅助应用程序,而不是键盘记录器或其他邪恶的东西。我已经查看了这个问题的其他实例,但它们似乎要么处理1)应用程序没有辅助启用或2)没有接收某些需要CGEvents接收的“特殊”命令键。我没有看到任何键,即使是简单的键(它已经通过我输入这个帖子而没有记录任何内容)。 TIA!
答案 0 :(得分:11)
所以,感谢Ken Thomases的上述问题,我能够弄清楚如何做到这一点。关键细节是我使用命令行应用程序模板(我不需要UI,所以我试图保持最小化)。给我的消息,但事后来看,只是创建一个运行循环不会创建一个事件循环。为了在命令行应用程序中复制事件循环的创建,必须使用典型的可可应用程序的更多内容。首先,您必须有一个实现NSApplicationDelegate协议的类,该委托将是应用程序代码所在的位置,主要方法是简单地执行以下操作:
#import <Foundation/Foundation.h>
#include "AppDelegate.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
AppDelegate *delegate = [[AppDelegate alloc] init];
NSApplication * application = [NSApplication sharedApplication];
[application setDelegate:delegate];
[NSApp run];
}
}
这是一个无笔尖,无菜单的应用程序,就像通常的命令行应用程序模板一样,但由于[NSApp run]
调用,它确实有一个真正的事件循环。然后我在上面的main方法中使用的应用程序代码移动到app delegate:
#import "AppDelegate.h"
@implementation AppDelegate
// 10.9+ only, see this url for compatibility:
// http://stackoverflow.com/questions/17693408/enable-access-for-assistive-devices-programmatically-on-10-9
BOOL checkAccessibility()
{
NSDictionary* opts = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts);
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
if (checkAccessibility()) {
NSLog(@"Accessibility Enabled");
}
else {
NSLog(@"Accessibility Disabled");
}
NSLog(@"registering keydown mask");
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
NSLog(@"keydown: %@", event.characters);
}];
}
@end
为了完整和未来的读者,头文件看起来像这样:
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
@end