2009-10-21 11 views
10

他のアプリケーションからグローバルキーイベント(ショートカット)を処理するために、CocoaプロジェクトでCarbonコードを使用しています。現在、私はkEventHotKeyReleasedイベントハンドラを設定しています。私のアプリケーションがアクティブでないときは、正常にホットキーを取得できます。それは私のアプリケーションで何らかの操作を引き起こします。(すべてのアプリケーションで)グローバル修飾キーの状態をどのように監視するのですか?

私はkEventHotKeyReleasedの行動を持っている問題は次のとおりです。例えば

言って、私はCMD-Shiftキーを押しながらPキーの組み合わせを押してください。 「P」キーを離すと、ホットキーイベントがトリガーされます。 すべてののキーがプッシュされていない場合は、(つまり、CmdキーとShiftキーも離しています)、イベントをトリガーする(または手動でトリガーする)必要があります。

ホットキーを監視するのは簡単ですが、個々のキーストロークの監視には何も見ていません。モディファイアのキーの状態を監視することができれば、私はビジネスになります。

これを行う方法に関するヒント?

ありがとうございます!


UPDATE:

私は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のために、何らかの理由で私は把握していないようすることができません。作られたか、何か他のものは、私が忘れてしまったする必要があり、追加の呼び出しがあります

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

:ここに私のglobalHotKeyHandler方法は次のようになりますか?

N.B:一見すると、ないそれは補助装置にアクセスが無効になっていることが考えられますように思えるが、。だから私はかなり無知だ。


UPDATE 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をイベントタップのマスクとして使用していますが、どういうわけか私は受け取っていますマウスダウンイベント ??


UPDATE 3:

[OK]を、私はこのパラメータにCGEventMaskBit(kCGEventKeyUp)を使用するとドキュメント内の行を見落としので、正しい呼び出しがある、ということを忘れて:

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

私はまだ問題があります:修飾キーはkCGEventKeyUpをトリガーしません。


UPDATE 4:

[OK]をもう一度...私はハァッ、今日それらを尋ねた後、私自身の質問5分に答えるためにバインドされてることを忘れて!修飾キーを傍受する

kCGEventFlagsChangedを使用します。

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

をだから、本質的に、私は、キーと修飾キーの状態検出作業を得たが、が、私はまだkEventRawKeyUpが動作しない理由を知ることに興味があります ...


NBは:また、私はOSの新しい、古いバージョンのサポートを持つことを目標にタイガーに開発していますのでご注意します できるだけ。 CGEventTapは10.4+しかないので、今のところこれを使用しますが、下位互換性のあるソリューションは大歓迎です。

答えて

3

EventTapsを使用することもできます。これにより、すべてのキーボードイベントを監視できます。参照: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

残念ながら、アプリケーションが安全な入力を要求している場合、イベントタップは機能しなくなります。たとえば、Quicken。

+0

モディファイアキーのみを監視する方法があると思います。 Googleのクイック検索ボックスのソースコードを確認してください。ユーザーがコマンドキーを2回タップしたときに検出するコードがあります。参照: http://www.google.com/codesearch/p?hl=ja&sa=N&cd=2&ct=rc#qWBe9JkJhME/trunk/QuickSearchBox/QSB/QSBApplicationDelegate.m&q=modifiersChangedWhileInactive%20package:http://qsb-mac \ .googlecode \。com – Leibowitzn

+0

ああ、彼らは次の炭素イベントに登録しているだけです: {kEventClassKeyboard、kEventRawKeyModifiersChanged} – Leibowitzn

+0

私はkEventRawKeyModifiersChangedとkEventRawKeyUpに気づきましたが、私の生活の中ではうまくいかないようです。私の質問の更新を参照してください。 (あなたの助けに感謝btw!) – Form

1
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL); 

これはグローバルではありません。これはあなたのアプリケーションがアクティブなときだけハンドラをインストールし、Carbon Event Manager自身のイベントフィルタの後に(私は)信じています。

InstallEventHandlerを使用する必要があります。は、最初のパラメータとしてイベントターゲットをとります(InstallApplicationEventHandlerは、アプリケーションイベントターゲットを渡すマクロです)。

アプリケーションがアクティブでない間に発生するイベントの場合、目的のターゲットはGetEventMonitorTarget()です。 である間に発生するイベントの場合、目的のターゲットはGetEventDispatcherTarget()です。どのアプリケーションがアクティブであってもイベントをキャッチするには、両方のターゲットにハンドラをインストールします。

しかし、私はCGEventTapsを使用していますが、Leibowitznが示唆しているとおりです。

+0

InstallApplicationEventHandlerは、自分のアプリケーションがアクティブである間だけでなく、ホットキーをどこにでもインストールするので奇妙です。どのアプリケーションからでもホットキーを起動できます。また、GetEventMonitorTarget()でInstallEventHandlerを使用しようとすると動作しないようですが、何か間違っている必要があります。 私は現在使用しているものの代わりにCGEventTapを使用するとどのような利点がありますか? – Form

+0

これはずっと簡単です。 –

+0

また、ホットキーを登録する場合は、[RegisterEventHotKey関数](http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/Reference/reference.html)を使用してホットキーを登録します。 #// apple_ref/c/func/RegisterEventHotKey)、その目的のために存在します。 –

関連する問題