15

CGEventTapCreateForPSNアプリケーションのキーをトラップおよびフィルタリングするために使用しています。他のアプリケーションのイベントをインターセプトすることに興味はありません。イベントタップは私の目的には重すぎると確信していますが、より良い方法を見つけることができず、イベントタップを使用すると機能します。

具体的には、このコードは私が望むことを行います。

GetCurrentProcess(&psn);
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);

また、コールバックは適切に処理され、イベントは現在のアプリケーションからのみインターセプトされます。

残念ながら、現在の値を取得するすべてのメソッドProcessSerialNumberは 10.9 で廃止されました。ProcessSerialNumberこの初期化により、同じプロセス内の他のルーチンに渡す古い標準的な方法があります...

ProcessSerialNumber psn = { 0, kCurrentProcess };

しかし、それは呼び出し時には機能しませんCGEventTapCreateForPSN。ヘッダー ファイル docs はそのことを示しており、次のコード スニペットは確認として返さNULLれます。

ProcessSerialNumber psn = { 0, kCurrentProcess };
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);

使用できますCGEventTapCreateが、ホスト全体をタップします。アプリケーションに向けられていないものをフィルタリングする必要があり、CGEventTapProxy不透明であり、それを使用して自分のアプリかどうかを判断する方法がわかりません。

廃止されたコードがまだ機能することを確認しましたが、Apple はいつでも削除することができます。CGEventTapCreateForPSNそれで、 Mavericks以降に電話をかけるためにどのように進めるべきか、誰か知っていますか?

ありがとう!


アップデート

10.11(エルキャピタンだったと思います)では、新しい機能が追加されました。ドキュメントはありませんが、 とほぼ同じ署名がありCGEventTapCreateForPSNます。

CFMachPortRef CGEventTapCreateForPSN(
    void *processSerialNumber,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);

CFMachPortRef CGEventTapCreateForPid(
    pid_t pid,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);

したがって、PID を最初のパラメーターとして使用できるため、非推奨の関数は必要ありません。

4

2 に答える 2

1

- (void)sendEvent:(NSEvent *)theEventこの目的のために、NSApplication をサブクラス化し、メソッドをオーバーライドする必要があると思います。ドキュメントから:

カスタム NSApplication サブクラスを作成する必要性はほとんどありません。一部のオブジェクト指向ライブラリとは異なり、Cocoa ではアプリの動作をカスタマイズするために NSApplication をサブクラス化する必要はありません。代わりに、アプリをカスタマイズするための他の多くの方法を提供します。

また:

重要

多くの AppKit クラスは NSApplication クラスに依存しており、このクラスが完全に初期化されるまで正しく動作しない可能性があります。そのため、たとえば、NSApplication サブクラスの初期化メソッドから他の AppKit クラスのメソッドを呼び出そうとしないでください。

したがって、アプリケーションを介して渡されたすべてのイベントをインターセプトし、NSApplicationDelegate を継承したカスタム プロトコル メソッドを呼び出すことができます。

// in SubApplication.h

@protocol ExtendedApplicationDelegate : NSApplicationDelegate

- (void)applicationDidTrapSomeInterestingEvent:(NSEvent *)event;

@end

// in SubApplication.m

- (void)sendEvent:(NSEvent *)event
{
    if ([event type] == NSKeyDown && [event keyCode]==_someCode)
    {
      // call application delegate method
    }
    [super sendEvent:event];
}

このアプローチで問題が解決するかどうかはわかりませんが、それでも試してみてください。

于 2015-05-20T14:06:18.843 に答える
0

もう 1 つの方法は、サブクラス化NSApplicationしてオーバーライドすることnextEventMatchingMask:untilDate:inMode:dequeue:です。sendEvent:これは、たとえば、スクロール バーを追跡するときなど、オーバーライドでは表示されないマウス イベントを表示します。質問があったキーボードイベントにとって重要かどうかはわかりませんが、この質問に出くわした他の人にとっては興味深いかもしれません。

于 2018-08-28T22:04:20.953 に答える