我发现upwork.app可以计算没有辅助功能访问的按键,但我无法理解它是如何完成的。
我读了很多像这样的主题: OSX: Detect system-wide keyDown events? 在所有主题中都说应该信任流程"启用辅助设备的访问权限#34;我无法找到upwork.app如何在没有这个的情况下跟踪密钥。 这是跟踪事件的官方文档: https://developer.apple.com/reference/appkit/nsevent/1535472-addglobalmonitorforeventsmatchin 来自docs - "如果启用了辅助功能,或者您的应用程序受信任以进行辅助功能访问(参见AXIsProcessTrusted),则只能监视与密钥相关的事件。"
在苹果邮件列表中说的是: http://lists.apple.com/archives/carbon-dev/2010/Feb/msg00043.html 我认为upwork.app使用了一些黑客。
如何计算没有辅助功能访问权限的按键?
答案 0 :(得分:5)
在评论中仍然没有收到你的回答,但由于这可能也会帮助其他人,无论如何我决定回答。
使用IOKit,您可以检测到键盘上有设备,并获取设备事件等按键事件。我已经用它来检测操纵杆事件,但它应该适用于键盘很好。我认为我所做的修改已经足够并且应该可行,但是我的Xcode现在正在更新,所以我还没有能够测试它。
KeyboardWatcher.h文件:
#import <Foundation/Foundation.h>
#import <IOKit/hid/IOHIDManager.h>
#import <IOKit/hid/IOHIDKeys.h>
@interface KeyboardWatcher : NSObject{
IOHIDManagerRef HIDManager;
}
@property (nonatomic) int keysPressedCount;
+(instancetype)sharedWatcher;
-(void)startWatching;
-(void)stopWatching;
@end
KeyboardWatcher.m文件:
#import "KeyboardWatcher.h"
@implementation KeyboardWatcher
static KeyboardWatcher *_sharedWatcher;
+(instancetype)sharedWatcher {
@synchronized([self class]) {
if (!_sharedWatcher){
_sharedWatcher = [[KeyboardWatcher alloc] init];
}
return _sharedWatcher;
}
return nil;
}
-(instancetype)init {
self = [super init];
if (self){
self.keysPressedCount = 0;
}
return self;
}
-(void)startWatching {
[self watchDevicesOfType:kHIDUsage_GD_Keyboard];
}
-(void)watchDevicesOfType:(UInt32)deviceType {
// Create an HID Manager
HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
// Create a Matching Dictionary
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// That will make the app just return the computer keyboards
CFDictionarySetValue(matchDict, CFSTR(kIOHIDPrimaryUsageKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &deviceType));
// Register the Matching Dictionary to the HID Manager
IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
// Register the HID Manager on our app’s run loop
IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
// Open the HID Manager
IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);
// Register input calls to Handle_DeviceEventCallback function
IOHIDManagerRegisterInputValueCallback(HIDManager, Handle_DeviceEventCallback, nil);
if (IOReturn) NSLog(@"IOHIDManagerOpen failed.");
}
-(void)stopWatching {
HIDManager = NULL;
}
static void Handle_DeviceEventCallback (void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef value){
IOHIDElementRef element = IOHIDValueGetElement(value); // Keyboard pressed key
uint32_t uniqueIdentifier = IOHIDElementGetCookie(element); // Unique ID of key
int elementValue = (int)IOHIDValueGetIntegerValue(value); // Actual state of key (1=pressed)
NSLog(@"Unique ID = %u; Value = %d", uniqueIdentifier, elementValue);
if (elementValue == 1) KeyboardWatcher.sharedWatcher.keysPressedCount++;
}
@end
如果您想确定哪个唯一ID是哪个键,您可以使用这些枚举(而不是导入Carbon,您只需创建一个CGKeyboardMapping.h
文件并将其粘贴到那里):
https://stackoverflow.com/a/16125341/4370893
最后,为了使用它,您只需要这样做就可以开始观看键盘事件了:
[[KeyboardWatcher sharedWatcher] startWatching];
获取按键次数:
[[KeyboardWatcher sharedWatcher] keysPressedCount];
要停下来:
[[KeyboardWatcher sharedWatcher] stopWatching];
这些是我编写原始操纵杆代码的参考资料:
一旦更新完成,我将测试代码,并确认它是否正常工作。
编辑:刚刚测试过,它正在运行。别忘了将IOKit框架添加到项目中。