如何监视全局修饰符键状态(在任何应用程序中)? [英] How to monitor global modifier key state (in any application)?

查看:296
本文介绍了如何监视全局修饰符键状态(在任何应用程序中)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的Cocoa项目中使用一些Carbon代码来处理来自其他应用程序的全局键事件(快捷键)。目前我已经设置了一个 kEventHotKeyReleased 事件处理程序,当我的应用程序不活动时,我可以成功获得热键。



我对 kEventHotKeyReleased 的行为的问题是:



说出例如我按Cmd-Shift-P组合键。一旦我释放P键,热键事件被触发。 我需要能够在所有键未按下时触发事件(或手动触发)(即:Cmd和Shift键也被释放)。



这是很容易监控热键,但我没有看到任何监控单个按键。



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



提前感谢!






更新: b $ b

我试过使用 kEventRawKeyUp kEventRawKeyModifiersChanged 但是 kEventHotKeyReleased 这两个工作,即使我以与 kEventHotKeyReleased 完全相同的方式设置它们。

  EventTypeSpec eventTypes [] = {{kEventClassKeyboard,kEventHotKeyReleased},{kEventClassKeyboard,kEventRawKeyUp}}; 
//改变列表中的顺序没有帮助,也不能删除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!
}

是否有额外的电话需要拨打或其他我忘记?



注意:乍一看,辅助装置的存取功能似乎已停用,但 不是强>。所以我很无能。






UPDATE 2: b

我调查了一下在 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代理,CGEventType类型,CGEventRef事件,void * refcon){
NSLog(@KeyUp event tapped!
return event;
}

正如你所看到的,我使用 kCGEventKeyUp 作为事件点按的掩码,但不知何故我收到 鼠标按下事件 ??






更新3:



确定忘记了,我忽略了在文档中说对该参数使用CGEventMaskBit(kCGEventKeyUp),因此正确的调用是:

  CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap ,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),& keyUpCallback,NULL); 

我仍然有问题:修饰键不触发kCGEventKeyUp ...






UPDATE 4:





要拦截修饰键,请使用 kCGEventFlagsChanged

  CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),& callbackFunction ,空值); 

因此,本质上我得到了键和修饰键的状态检测工作,但仍然有兴趣了解为什么 kEventRawKeyUp 无效 ...



< hr>

注意:还要注意,我在Tiger上开发,目标是尽可能支持新的和旧版本的操作系统。

解决方案

一个可以使用的解决方案选项是使用EventTaps。这样可以监视所有键盘事件。请参阅:
http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate



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


I'm using some Carbon code in my Cocoa project for handling global key events (shortcuts) from other applications. Currently I have setup a kEventHotKeyReleased event handler and I can successfully obtain hot keys when my application is not active. That triggers some operation in my application.

The problem I have with the behavior of kEventHotKeyReleased is:

Say for example I press the Cmd-Shift-P key combination. As soon as I release the "P" key the hot key event is triggered. I need to be able to trigger the event (or manually trigger it) when all of the keys are unpressed (i.e: the Cmd and Shift keys are released too).

It is easy to monitor for hot keys but I have seen nothing for monitoring individual keystrokes. If I could monitor the modifier key states I would be in business.

Any hints on how to do this?

Thanks in advance!


UPDATE:

I've tried using kEventRawKeyUp and kEventRawKeyModifiersChanged but while kEventHotKeyReleased works those two don't even though I set them up in the exact same way as 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

The globalHotKeyHandler method is called for kEventHotKeyReleased, but not for kEventRawKeyUp for some reason I can't seem to grasp. Here's what my globalHotKeyHandler method looks like:

OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
    NSLog(@"Something happened!");
}

Is there an additional call that needs to be made or something else I forgot?

N.B: At first glance, it seems like it could be that Access for Assistive Devices is disabled but it is not. So I'm pretty clueless.


UPDATE 2:

I investigated a bit on the CGEventTap Leibowitzn suggested and I came up with this setup:

CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);

... and the callback:

CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"KeyUp event tapped!");
    return event;
}

As you can see I'm using kCGEventKeyUp as the mask for the event tap but somehow I'm receiving mouse down events ??!??


UPDATE 3:

Ok forget that, I overlooked the line in the doc that said to use CGEventMaskBit(kCGEventKeyUp) for this parameter, so the correct call is:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);

I'm still having a problem though: modifier keys do not trigger the kCGEventKeyUp...


UPDATE 4:

Ok forget that again... I'm bound to answer to my own questions 5 minutes after asking them today huh!

To intercept modifier keys, use kCGEventFlagsChanged:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);

So in essence I got the key and modifier key state detection working, but I'm still interested in knowing why kEventRawKeyUp doesn't work...


N.B: Also note that I'm developing on Tiger with the goal of having support for new and older versions of the OS as much as possible. CGEventTap is 10.4+ only so I'll be using this for now but a backwards-compatible solution would be welcome.

解决方案

One option is to use EventTaps. This lets you monitor all keyboard events. See: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

Unfortunately event taps will stop working if an application is requesting secure input. For example Quicken.

这篇关于如何监视全局修饰符键状态(在任何应用程序中)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆