(任意のアプリケーションで) グローバル修飾キーの状態を監視するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/1603030

  •  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 を使用するだけです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top