【发布时间】:2009-10-21 19:23:25
【问题描述】:
我在我的 Cocoa 项目中使用了一些 Carbon 代码来处理来自其他应用程序的全局键事件(快捷方式)。目前我已经设置了一个kEventHotKeyReleased 事件处理程序,当我的应用程序不活动时我可以成功获取热键。这会在我的应用程序中触发一些操作。
kEventHotKeyReleased 的行为问题是:
例如,我按下 Cmd-Shift-P 组合键。只要我松开“P”键,就会触发热键事件。 当所有键都未按下(即:Cmd 和 Shift 键也被释放)时,我需要能够触发事件(或手动触发它)。
监视热键很容易,但我没有看到监视单个键击的任何内容。如果我可以监控修饰键状态,我会做生意的。
关于如何做到这一点的任何提示?
提前致谢!
更新:
我尝试过使用kEventRawKeyUp 和kEventRawKeyModifiersChanged,但是虽然kEventHotKeyReleased 可以使用这两个方法,但我的设置方式与kEventHotKeyReleased 完全相同。
EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line
globalHotKeyHandler 方法是为 kEventHotKeyReleased 调用的,但不是为 kEventRawKeyUp 调用的,出于某种我似乎无法理解的原因。这是我的globalHotKeyHandler 方法的样子:
OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
NSLog(@"Something happened!");
}
是否还有其他需要拨打的电话或其他我忘记的电话?
N.B:乍一看,辅助设备访问似乎被禁用,但不是。所以我很无知。
更新 2:
我对@987654333@ Leibowitzn 的建议进行了一些调查,然后我想出了这个设置:
CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);
...和回调:
CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(@"KeyUp event tapped!");
return event;
}
如您所见,我使用kCGEventKeyUp 作为事件点击的掩码,但不知何故我收到了鼠标按下事件 ??!??
更新 3:
好吧,忘记了,我忽略了文档中说使用 CGEventMaskBit(kCGEventKeyUp) 作为这个参数的那一行,所以正确的调用是:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);
我仍然有一个问题:修饰键不会触发 kCGEventKeyUp...
更新 4:
好吧,再次忘记这一点......我一定会在今天问他们 5 分钟后回答我自己的问题哈!
要拦截修饰键,请使用kCGEventFlagsChanged:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);
所以本质上我让键和修饰键状态检测工作正常,但是我仍然想知道为什么kEventRawKeyUp 不起作用...
N.B:另外请注意,我正在 Tiger 上进行开发,目标是尽可能多地支持新旧版本的操作系统。 CGEventTap 仅 10.4+,所以我现在将使用它,但欢迎使用向后兼容的解决方案。
【问题讨论】:
标签: objective-c cocoa macos-carbon