13

OSX でキーストロークをシミュレートする必要があります。これが私がそれを行う方法です:

-(void)execute {
    CGEventSourceRef sourceRef =
    CGEventSourceCreate(kCGEventSourceStateHIDSystemState);

    CGEventRef keyPress = CGEventCreateKeyboardEvent (sourceRef, (CGKeyCode)keyCode, true);
    CGEventRef keyUnpress = CGEventCreateKeyboardEvent (sourceRef, (CGKeyCode)keyCode, false);

    CGEventSetFlags(keyPress, modifierFlags);
    CGEventPost(kCGHIDEventTap, keyPress);

    //unpressing the acualkey
    CGEventPost(kCGHIDEventTap, keyUnpress);

    CFRelease(keyPress);
    CFRelease(keyUnpress);
    CFRelease(sourceRef);
}

どのアプリのすべてのホットキーまたは単純なキーストロークでも問題なく機能しますが、option + spaceSpotlight の起動cmd + shift + 4、スクリーンショットの作成、ctrl + `iTerm2 ウィンドウを開くなど、システム全体のショートカットでは機能しません。

イベントのソースとイベントを投稿する場所を変更しようとしましたが、役に立ちません。何か案は?

4

4 に答える 4

17

CGEventCreateKeyboardEvent のドキュメントから:

修飾キーを含め、文字の生成に必要なすべてのキーストロークを入力する必要があります。たとえば、「Z」を生成するには、SHIFT キーを押し、「z」キーを押してから、SHIFT キーと「z」キーを離す必要があります。

そのため、オプション修飾子を使用してスペースを押して放すだけで、オプションスペースをトリガーすることはできません。オプションを押し、スペースを押し、スペースを解放し、オプションを解放する必要があります。

ちなみに、 opt-space はデフォルトでは何もしません。cmd-space は Spotlight 検索のホットキーで、cmd-opt-space は Spotlight ウィンドウのホットキーです。

したがって、このコードは Spotlight 検索をポップアップ表示します。

- (void)execute {
  CGEventSourceRef src = 
    CGEventSourceCreate(kCGEventSourceStateHIDSystemState);

  CGEventRef cmdd = CGEventCreateKeyboardEvent(src, 0x38, true);
  CGEventRef cmdu = CGEventCreateKeyboardEvent(src, 0x38, false);
  CGEventRef spcd = CGEventCreateKeyboardEvent(src, 0x31, true);
  CGEventRef spcu = CGEventCreateKeyboardEvent(src, 0x31, false);

  CGEventSetFlags(spcd, kCGEventFlagMaskCommand);
  CGEventSetFlags(spcu, kCGEventFlagMaskCommand);

  CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works
  CGEventPost(loc, cmdd);
  CGEventPost(loc, spcd);
  CGEventPost(loc, spcu);
  CGEventPost(loc, cmdu);

  CFRelease(cmdd);
  CFRelease(cmdu);
  CFRelease(spcd);
  CFRelease(spcu);
  CFRelease(src);  
}
于 2012-05-24T21:33:44.113 に答える
11

CGKeyCodeリストが必要な他の人のために、ここに部分的なテーブルを持つRUIプロジェクトの関数があります。

これより完全な例かもしれませんが。より完全な地図を知っている人はいますか?

int keyCodeForKeyString(char * keyString);  // get the Mac keycode for the RUI representation

int keyCodeForKeyString(char * keyString)
{
    if (strcmp(keyString, "a") == 0) return 0;
    if (strcmp(keyString, "s") == 0) return 1;
    if (strcmp(keyString, "d") == 0) return 2;
    if (strcmp(keyString, "f") == 0) return 3;
    if (strcmp(keyString, "h") == 0) return 4;
    if (strcmp(keyString, "g") == 0) return 5;
    if (strcmp(keyString, "z") == 0) return 6;
    if (strcmp(keyString, "x") == 0) return 7;
    if (strcmp(keyString, "c") == 0) return 8;
    if (strcmp(keyString, "v") == 0) return 9;
    // what is 10?
    if (strcmp(keyString, "b") == 0) return 11;
    if (strcmp(keyString, "q") == 0) return 12;
    if (strcmp(keyString, "w") == 0) return 13;
    if (strcmp(keyString, "e") == 0) return 14;
    if (strcmp(keyString, "r") == 0) return 15;
    if (strcmp(keyString, "y") == 0) return 16;
    if (strcmp(keyString, "t") == 0) return 17;
    if (strcmp(keyString, "1") == 0) return 18;
    if (strcmp(keyString, "2") == 0) return 19;
    if (strcmp(keyString, "3") == 0) return 20;
    if (strcmp(keyString, "4") == 0) return 21;
    if (strcmp(keyString, "6") == 0) return 22;
    if (strcmp(keyString, "5") == 0) return 23;
    if (strcmp(keyString, "=") == 0) return 24;
    if (strcmp(keyString, "9") == 0) return 25;
    if (strcmp(keyString, "7") == 0) return 26;
    if (strcmp(keyString, "-") == 0) return 27;
    if (strcmp(keyString, "8") == 0) return 28;
    if (strcmp(keyString, "0") == 0) return 29;
    if (strcmp(keyString, "]") == 0) return 30;
    if (strcmp(keyString, "o") == 0) return 31;
    if (strcmp(keyString, "u") == 0) return 32;
    if (strcmp(keyString, "[") == 0) return 33;
    if (strcmp(keyString, "i") == 0) return 34;
    if (strcmp(keyString, "p") == 0) return 35;
    if (strcmp(keyString, "RETURN") == 0) return 36;
    if (strcmp(keyString, "l") == 0) return 37;
    if (strcmp(keyString, "j") == 0) return 38;
    if (strcmp(keyString, "'") == 0) return 39;
    if (strcmp(keyString, "k") == 0) return 40;
    if (strcmp(keyString, ";") == 0) return 41;
    if (strcmp(keyString, "\\") == 0) return 42;
    if (strcmp(keyString, ",") == 0) return 43;
    if (strcmp(keyString, "/") == 0) return 44;
    if (strcmp(keyString, "n") == 0) return 45;
    if (strcmp(keyString, "m") == 0) return 46;
    if (strcmp(keyString, ".") == 0) return 47;
    if (strcmp(keyString, "TAB") == 0) return 48;
    if (strcmp(keyString, "SPACE") == 0) return 49;
    if (strcmp(keyString, "`") == 0) return 50;
    if (strcmp(keyString, "DELETE") == 0) return 51;
    if (strcmp(keyString, "ENTER") == 0) return 52;
    if (strcmp(keyString, "ESCAPE") == 0) return 53;

    // some more missing codes abound, reserved I presume, but it would
    // have been helpful for Apple to have a document with them all listed

    if (strcmp(keyString, ".") == 0) return 65;

    if (strcmp(keyString, "*") == 0) return 67;

    if (strcmp(keyString, "+") == 0) return 69;

    if (strcmp(keyString, "CLEAR") == 0) return 71;

    if (strcmp(keyString, "/") == 0) return 75;
    if (strcmp(keyString, "ENTER") == 0) return 76;  // numberpad on full kbd

    if (strcmp(keyString, "=") == 0) return 78;

    if (strcmp(keyString, "=") == 0) return 81;
    if (strcmp(keyString, "0") == 0) return 82;
    if (strcmp(keyString, "1") == 0) return 83;
    if (strcmp(keyString, "2") == 0) return 84;
    if (strcmp(keyString, "3") == 0) return 85;
    if (strcmp(keyString, "4") == 0) return 86;
    if (strcmp(keyString, "5") == 0) return 87;
    if (strcmp(keyString, "6") == 0) return 88;
    if (strcmp(keyString, "7") == 0) return 89;

    if (strcmp(keyString, "8") == 0) return 91;
    if (strcmp(keyString, "9") == 0) return 92;

    if (strcmp(keyString, "F5") == 0) return 96;
    if (strcmp(keyString, "F6") == 0) return 97;
    if (strcmp(keyString, "F7") == 0) return 98;
    if (strcmp(keyString, "F3") == 0) return 99;
    if (strcmp(keyString, "F8") == 0) return 100;
    if (strcmp(keyString, "F9") == 0) return 101;

    if (strcmp(keyString, "F11") == 0) return 103;

    if (strcmp(keyString, "F13") == 0) return 105;

    if (strcmp(keyString, "F14") == 0) return 107;

    if (strcmp(keyString, "F10") == 0) return 109;

    if (strcmp(keyString, "F12") == 0) return 111;

    if (strcmp(keyString, "F15") == 0) return 113;
    if (strcmp(keyString, "HELP") == 0) return 114;
    if (strcmp(keyString, "HOME") == 0) return 115;
    if (strcmp(keyString, "PGUP") == 0) return 116;
    if (strcmp(keyString, "DELETE") == 0) return 117;
    if (strcmp(keyString, "F4") == 0) return 118;
    if (strcmp(keyString, "END") == 0) return 119;
    if (strcmp(keyString, "F2") == 0) return 120;
    if (strcmp(keyString, "PGDN") == 0) return 121;
    if (strcmp(keyString, "F1") == 0) return 122;
    if (strcmp(keyString, "LEFT") == 0) return 123;
    if (strcmp(keyString, "RIGHT") == 0) return 124;
    if (strcmp(keyString, "DOWN") == 0) return 125;
    if (strcmp(keyString, "UP") == 0) return 126;

    fprintf(stderr, "keyString %s Not Found. Aborting...\n", keyString);
    exit(EXIT_FAILURE);
}
于 2012-10-22T02:46:23.737 に答える
5

ちなみに、@ abarnertの答えは素晴らしく、ドキュメントによるとそれを行う必要がありますが、私の元のコードも機能します。この質問とは関係のない別の問題があることがわかりました。

したがって、キープレスに修飾キーを適用する必要がある場合は、CGEventSetFlags(keyPress, modifierFlags);すべての修飾キーを個別に押すことなく、このように修飾キーを追加するだけで済みます。そのアプローチは機能しますが、私はまだ欠点を発見しておらず、コードの可読性ははるかに優れています。

于 2012-05-28T13:31:14.790 に答える