objective-c - 如何监控全局修改键状态(在任何应用程序中)?

标签 objective-c cocoa macos-carbon

我在我的 Cocoa 项目中使用一些 Carbon 代码来处理来自其他应用程序的全局键事件(快捷方式)。目前我已经设置了一个 kEventHotKeyReleased事件处理程序,当我的应用程序未处于事件状态时,我可以成功获取热键。这会在我的应用程序中触发一些操作。

我对 kEventHotKeyReleased 的行为有疑问是:

例如,我按下了 Cmd-Shift-P 组合键。只要我松开“P”键,就会触发热键事件。 我需要能够在所有键未按下时触发事件(或手动触发)(即:Cmd 和 Shift 键也被释放)。

监视热键很容易,但我没有看到任何用于监视单个击键的东西。如果我可以监控修饰键状态,我就可以做生意了。

关于如何执行此操作的任何提示?

提前致谢!


更新:

我试过使用 kEventRawKeyUpkEventRawKeyModifiersChanged但是虽然 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!");
}

是否需要调用其他电话或我忘记的其他电话?

注意:乍一看,辅助设备的访问似乎被禁用,但它不是。所以我很无能。


更新 2:

我调查了一下 CGEventTap 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不工作...


注意:另请注意,我在 Tiger 上进行开发的目的是尽可能支持新旧版本的操作系统。 CGEventTap 仅为 10.4+,所以我现在将使用它,但欢迎使用向后兼容的解决方案。

最佳答案

一种选择是使用 EventTaps。这使您可以监视所有键盘事件。看: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

不幸的是,如果应用程序请求安全输入,事件点击将停止工作。例如 Quicken。

关于objective-c - 如何监控全局修改键状态(在任何应用程序中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1603030/

相关文章:

objective-c - 由于模拟器错误,回退到从 NSUserDefaults 加载访问 token

cocoa - 通过 Cocoa Bindings 获取核心数据中关系的最后一个元素的正确方法

SwiftUI 文本动画不透明度不起作用

ios - 自动布局约束没有得到尊重

ios - 如何使用 NS_RETURNS_INNER_POINTER 标志

iphone - 为什么[UIColor白色]和黑色的亮度相等

objective-c - 碳和 cocoa 的区别?

cocoa - 使用辅助功能 API 设置最前面的窗口

macos - Mac OS X Carbon : What is the difference between SelectWindow vs. ActivateWindow 以及 Cocoa 的等效项是什么

iOS REST 设计模式建议