(任意のアプリケーションで) グローバル修飾キーの状態を監視するにはどうすればよいですか?
-
05-07-2019 - |
質問
他のアプリケーションからのグローバル キー イベント (ショートカット) を処理するために、Cocoa プロジェクトでいくつかの Carbon コードを使用しています。現在、私はセットアップしています kEventHotKeyReleased
イベント ハンドラを使用すると、アプリケーションがアクティブでないときでもホット キーを正常に取得できます。これにより、アプリケーションで何らかの操作がトリガーされます。
~の行動に関して私が抱えている問題 kEventHotKeyReleased
は:
たとえば、Cmd-Shift-P キーの組み合わせを押したとします。「P」キーを放すとすぐにホット キー イベントがトリガーされます。 次の場合にイベントをトリガーできる (または手動でトリガーできる) 必要があります。 全て キーが押されていない (つまり:Cmd キーと Shift キーも放します)。
ホットキーを監視するのは簡単ですが、個々のキーストロークを監視するものは見たことがありません。修飾キーの状態を監視できれば、仕事になるでしょう。
これを行う方法についてヒントはありますか?
前もって感謝します!
アップデート:
使ってみた kEventRawKeyUp
そして kEventRawKeyModifiersChanged
しかしその間 kEventHotKeyReleased
とまったく同じ方法で設定したにもかかわらず、これら2つは機能しません 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
機能しない...
注意:また、私は新しいバージョンと古いバージョンの OS をできる限りサポートすることを目標として Tiger で開発していることにも注意してください。CGEventTap は 10.4 以降のみなので、今のところこれを使用しますが、下位互換性のあるソリューションは歓迎されます。
解決
1 つのオプションは、EventTaps を使用することです。これにより、すべてのキーボード イベントを監視できます。見る:http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate
残念ながら、アプリケーションが安全な入力を要求している場合、イベント タップは機能しなくなります。例えばクイッケン。
他のヒント
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
これは世界的なものではありません。これにより、独自のアプリケーションがアクティブなとき、および (おそらく) Carbon Event Manager 独自のイベント フィルターの後にのみハンドラーがインストールされます。
使用する必要があります InstallEventHandler
, 、イベントターゲットを最初のパラメータとして受け取ります(InstallApplicationEventHandler
はアプリケーション イベント ターゲットを渡すマクロです)。
アプリケーションがアクティブでない間に発生するイベントの場合、必要なターゲットは GetEventMonitorTarget()
. 。アプリケーション中に発生するイベントの場合 は アクティブな場合、必要なターゲットは GetEventDispatcherTarget()
. 。どのアプリケーションがアクティブであってもイベントをキャッチするには、両方のターゲットにハンドラーをインストールします。
ただし、最近では、Leibowitzn が提案したように、CGEventTaps を使用するだけです。