在OSX系统全局监听键盘的按下事件,并可以捕获事件源的硬件的接口位置,用于区分是哪个键盘产生的事件。下面的代码只是以键盘为例子,其实是可以适用于其他输入外设的。如有需要可搜索相关外设的匹配字典的创建代码。

设备匹配字典

CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage,  UInt32 usage )
{
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
kCFAllocatorDefault,
, & kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks );
if ( ! dict )
return NULL; CFNumberRef pageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usagePage );
if ( ! pageNumberRef ) {
CFRelease( dict );
return NULL;
} CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef );
CFRelease( pageNumberRef ); CFNumberRef usageNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, & usage ); if ( ! usageNumberRef ) {
CFRelease( dict );
return NULL;
} CFDictionarySetValue( dict, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef );
CFRelease( usageNumberRef ); return dict;
}

事件的回调函数

void myHIDKeyboardCallback(void* context,  IOReturn result,  void* sender,  IOHIDValueRef value )
{
//get device product id and vendor id
IOHIDDeviceRef device = sender;
// int32_t pid = 1;
// CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberSInt32Type, &pid);
// int32_t vendorID = 0;
// CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberSInt32Type, &vendorID);
// NSLog(@"vendor:%d product:%d", vendorID, pid); IOHIDElementRef elem = IOHIDValueGetElement( value ); // if (IOHIDElementGetUsagePage(elem) != 0x07)
// return; uint32_t scancode = IOHIDElementGetUsage( elem ); if (scancode < || scancode > )
return; int32_t locationID = ;
CFNumberGetValue(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey)), kCFNumberSInt32Type, &locationID);
NSLog(@"location:%d", locationID); long pressed = IOHIDValueGetIntegerValue( value );
uint64_t timestamp = IOHIDValueGetTimeStamp(value);
printf( "scancode: %3d, %s timestamp:%llu \n", scancode, pressed?"keydown":"keyup ", timestamp); //send the keyboard event
NSDictionary* userInfo = [[NSDictionary alloc]initWithObjectsAndKeys:
[NSNumber numberWithInt:scancode], NOTIFICATION_KEY_ScanCode,
[NSNumber numberWithInt:locationID], NOTIFICATION_KEY_Location,
[NSNumber numberWithLong:pressed], NOTIFICATION_KEY_IsKeyDown,
[NSNumber numberWithLong:timestamp], NOTIFICATION_KEY_Timestamp, nil];
NSNotification* notification = [NSNotification notificationWithName:NOTIFICATION_KeyBoardEvent object:nil userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:notification]; UsbSignalController* controller = (__bridge UsbSignalController*)context;
[controller onKeyEvent:scancode Location:locationID IsDown:pressed Timestamp:timestamp];
}

注册键盘钩子

-(void)registerKeyboardHook
{
IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone ); CFMutableDictionaryRef keyboard = myCreateDeviceMatchingDictionary( 0x01, );
CFArrayRef matches;
{
//CFMutableDictionaryRef keypad = myCreateDeviceMatchingDictionary( 0x01, 7 );
CFMutableDictionaryRef matchesList[] = { keyboard/*, keypad*/ };
matches = CFArrayCreate( kCFAllocatorDefault, (const void **)matchesList, /**/, NULL );
} IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches );
CFRelease(matches);
CFRelease(keyboard ); IOHIDManagerRegisterInputValueCallback(hidManager, myHIDKeyboardCallback, (__bridge void*)self);
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode );
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone );
}

OSX监听全局键盘按下事件并捕获事件源的硬件接口位置的更多相关文章

  1. Flex 自动获取焦点 监听全局键盘事件

    在mxml里监听addedToStage事件 protected function application1_addedToStageHandler(event:Event):void { this. ...

  2. Python——pyHook监听鼠标键盘事件

    pyHook包为Windows中的全局鼠标和键盘事件提供回调. 底层C库报告的信息包括事件的时间,事件发生的窗口名称,事件的值,任何键盘修饰符等. 而正常工作需要pythoncom等操作系统的API的 ...

  3. WPF - 监听判断键盘组合键的按下

    对于键盘事件PreviewKeyDown.PreviewKeyUp.KeyDown.KeyUp,在其中检查当次事件是哪个按键触发的很简单,只需要判断KeyEventArgs类型的事件参数e的Key属性 ...

  4. Android 另类方法监听软键盘的弹出收起事件

    http://www.cnblogs.com/csonezp/p/5065624.html 最近做的项目碰到个问题,a界面是fragment+recyclerview,b界面带个edittext,并且 ...

  5. KeyDown/PreviewKeyDown事件中监听Alt键按下

    一个坑 在WPF应用程序(或者其他Windows应用程序中),为了监听Alt键按下,我们可以尝试写出这样的代码: PreviewKeyDown += (s, e) => { if (e.Key ...

  6. adnroid 监听软键盘的显隐

    首先注明出处,我只是想做个笔记:http://www.jb51.net/article/64820.htm 第一眼看到的时候,觉得不太可靠,因为之前都是看到这样处理的,根据监听一个根布局的size,可 ...

  7. Android App监听软键盘按键的三种方式

    前言:   我们在android手机上面有时候会遇到监听手机软键盘按键的时候,例如:我们在浏览器输入url完毕后可以点击软键盘右下角的“GO”按键加载url页面:在点击搜索框的时候,点击右下角的sea ...

  8. 键盘-App监听软键盘按键的三种方式

    前言:   我们在android手机上面有时候会遇到监听手机软键盘按键的时候,例如:我们在浏览器输入url完毕后可以点击软键盘右下角的“GO”按键加载url页面:在点击搜索框的时候,点击右下角的sea ...

  9. Android App监听软键盘按键的三种方式(转)

    最近有类似需求,在csdn上刚好发现,粘贴过来,以防止忘记喽 前言:   我们在android手机上面有时候会遇到监听手机软键盘按键的时候,例如:我们在浏览器输入url完毕后可以点击软键盘右下角的“G ...

随机推荐

  1. Android 实现透明效果的 Activity

    Android系统提供了将Activity设置为透明的主题:@android:style/Theme.Translucent 该属性同一时候支持隐藏TitleBar和全屏显示. 仅仅须要在Androi ...

  2. iOS核心动画 - CALayer

    大家知道,在iOS中所有的视图都继承自UIView. UIView处理所有的触摸事件和画图. 事实上,UIView所有的渲染和动画是托管给另一个类来负责的,它就是CALayer. 但是,需要记住的是, ...

  3. 创建sdcard.img时,提示permission dennid

    解决方法: mksdcard -l sdcard 100M E:\sdcard\sdcard.img 换一个盘试试,比如:mksdcard -l sdcard 100M F:\sdcard\sdcar ...

  4. edge中断分析

    眼下正在调试msix中断,在測试过程中发现会概率性的丢失中断.Msix中断默认是edge触发的中断,edge触发的中断是在中断相应pin发生电平信号跳变的时候,会发出一个中断请求. 由于跳变是一瞬间的 ...

  5. SlidingMenu(一)

    我们一般称之为侧边栏,今天下倒腾了一下,留点笔记... 源码来自:https://github.com/jfeinstein10/SlidingMenu 来张图把: 代码API注释看看这个吧 http ...

  6. DBMS_METADATA中使用SESSION_TRANSFORM过滤不想获取的DDL

    我们一般使用dbms_metadata.get_ddl获取对象的ddl的时候,有时会获取一些其它额外的信息,比如当你想获取表的创建语句的时候,你会得到表的约束信息,这个信息可能是你不想要的,那么就能够 ...

  7. js无缝滚动,不平滑(求高人指点)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  8. cygwin下安装scws

    安装gcc和make命令 1.找到cygwin的etc目录中有一个名为passwd的文件.   2.用UE或记事本打开passwd这个文件,找到以下部分,把其中的windows用户名admin换成ro ...

  9. 解决Enter键与input 、a标签触发的事件的冲突

    无论是 <button type="button" onclick="console.log('123');">123</button> ...

  10. linux CentOs 权限导致的Apache - "DocumentRoot must be a directory"的解决方案

    在配置apache服务时经常遇到DocumentRoot must be a directory的错误提示,刚接触到apache时折腾了几个小时才找到错误的原因,出现这样的错误一般都是由于selinu ...