Отправить автоматически повторяемый ключ с использованием методов CoreGraphics (Mac OS X Snow Leopard) - PullRequest
3 голосов
/ 19 апреля 2011

Я успешно отправил нажатия клавиш, чтобы автоматизировать определенный пакет программного обеспечения для рисования, которое я использую.Это программное обеспечение использует множество сочетаний клавиш, поэтому я написал кое-что, что могло бы вызвать некоторые из этих сочетаний клавиш, чтобы упростить мой рабочий процесс.Как я уже сказал, это сработало хорошо.

Моя библиотека - это библиотека Какао, которая загружается как плагин в программный пакет.Вот фрагмент кода, который я использовал для отправки своих нажатий клавиш.

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
CGEventRef eventUp = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, false);

//setting the process number somewhere else
CGEventPostToPSN(&number, eventDown);
CGEventPostToPSN(&number, eventUp);

Для некоторых процедур в пакете рисования, если вы продолжаете удерживать клавишу Shift, тогда вы активируете специальный инструмент.Я не смог смоделировать это.Я подумал, что могу отправить клавишу Shift и сказать, что я хочу, чтобы она автоматически повторялась, но, похоже, это не работает.Я использовал следующий код для установки автоповтора:

//This is done before sending the key
CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);

В моем тестировании я не смог сделать ни одного ключа автоповтора.Просто отправьте ключ один раз и все.

Есть ли кто-нибудь, кто успешно повторил ключ, используя описанный выше метод?Я искал в Интернете ответы, но все, что я нашел, это некоторые оставшиеся без ответа вопросы 2008 года ... Любая помощь очень ценится.

Спасибо,

mobbe

Ответы [ 2 ]

1 голос
/ 21 апреля 2011

Код, который наконец-то разработал OP для решения проблемы (перенесен сюда из комментария под другим ответом):

CGEventRef flagsChanged = CGEventCreate(eventSource); 
CGEventSetType(flagsChanged, kCGEventFlagsChanged); 
CGEventSetIntegerValueField(flagsChanged, kCGKeyboardEventKeycode, 56);     
CGEventSetFlags(flagsChanged, 131330); 
CGEventPostToPSN(&number, flagsChanged); 
CFRelease(flagsChanged); CFRelease(eventSource);

131330 - это константа, обозначающая клавишу Shift;это относится к NSShiftKeyMask и kCGEventFlagMaskShift, которые 131072 (0x00020000).131330 - 256 - 2 == 131072.

1 голос
/ 19 апреля 2011

ОБНОВЛЕНИЕ: код клавиши Shift не 56, согласно Events.h:

...
kVK_Shift                     = 0x38,
...

(РЕДАКТИРОВАТЬ: конечно, те из вас, кто обращает внимание (я не был), понимают, что HEX 38 == 56 декабря.)

Я также понял, как получить нажатия клавиш-модификаторов: flagsChanged:. Таким образом, используя этот код клавиши, я могу отловить нажатия клавиш Shift в flagsChanged:, и повтор работает отлично; Я также получаю повторяющиеся события клавиш для «обычных» клавиш в keyDown: и keyUp: без затруднений.

Звучит так, что у вас может не быть доступа к желаемому изменению кода обработки событий (чтобы добавить flagsChanged:), или вы хотите изменить его, поэтому, если этот код ключа не работает для вас, я озадачен и могу только сказать " Удачи! "


Я полагаю, что поле, которое вы устанавливаете, используется не для того, чтобы указать, что событие должно быть повторено системой, а для того, чтобы событие было автоматическим повторением Предыдущее событие Вы все еще должны генерировать каждое событие самостоятельно. Что-то вроде (ИЗМЕНЕНО для использования таймера вместо цикла):

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
// Post the initial keydown
CGEventPostToPSN(&pidNumber, eventDown);

// Keep track of how many Shift keydown events have been sent
shiftKeyRepeatCount = 1;
[NSTimer scheduledTimerWithTimeInterval:0.3    // I don't know exactly what the interval should be, of course
                                 target:self
                               selector:@selector(repeatShiftKeyDown:)
                               userInfo:nil
                                repeats:YES];

CFRelease(eventDown);

- (void)repeatShiftKeyDown:(NSTimer *)tim {
    if( shiftKeyRepeatCount >= kRepeatCountForSpecialTool ){
        [tim invalidate];
        [self sendShiftKeyUp];
        return;
    }
    shiftKeyRepeatCount++;
    GEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
    // Set the auto-repeat field
    CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);
    CGEventPostToPSN(&pidNumber, eventDown);
    CFRelease(eventDown);
}

Я не уверен, можете ли вы повторно использовать первое событие с измененным полем, или вам нужно будет сгенерировать новое событие для повторения.

...