Измените NSEvent для отправки другого ключа, кроме того, который был нажат

Я пытаюсь создать крючок для клавиатуры OS X для вспомогательных технологий (т. Е. Не беспокойтесь, а не кейлоггер).

Когда пользователь нажимает клавишу, я хочу предотвратить реальное нажатие клавиши и отправить вместо этого поддельное нажатие (символ по моему выбору).

У меня есть следующий код:

- (void) hookTheKeyboard { CGEventMask keyboardMask = CGEventMaskBit(kCGEventKeyDown); id eventHandler = [NSEvent addGlobalMonitorForEventsMatchingMask:keyboardMask handler:^(NSEvent *keyboardEvent) { NSLog(@"keyDown: %c", [[keyboardEvent characters] characterAtIndex:0]); //Want to: Stop the keyboard input //Want to: Send another key input instead }]; } 

Любая помощь в достижении этих целей? В основном изменение NSEvent «keyboardEvent» для отправки другого символа. Благодарю.

Вы не можете сделать это с NSEvent API NSEvent , но вы можете сделать это с помощью CGEventTap . Вы можете создать активное событие и зарегистрировать обратный вызов, который получает CGEventRef и может его модифицировать (при необходимости) и вернуть его для изменения реального streamа событий.


РЕДАКТИРОВАТЬ

Вот простая программа, которая во время работы заменяет каждое «b» нажатие клавиши «v»:

 #import  CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { //0x0b is the virtual keycode for "b" //0x09 is the virtual keycode for "v" if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 0x0B) { CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, 0x09); } return event; } int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; CFRunLoopSourceRef runLoopSource; CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL); if (!eventTap) { NSLog(@"Couldn't create event tap!"); exit(1); } runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); CGEventTapEnable(eventTap, true); CFRunLoopRun(); CFRelease(eventTap); CFRelease(runLoopSource); [pool release]; exit(0); } 

(Смешная история: когда я редактировал этот пост, я продолжал пытаться писать «заменяет каждое« b »нажатие клавиши», но он продолжал появляться как «заменяет каждое« v »нажатие клавиши. Я был в замешательстве. Тогда я вспомнил, что Я еще не остановил приложение.)

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

  • Я перехватил событие в окне, создав переопределение для sendEvent :. Затем я проверяю ключевые события (KeyUp или KeyDown), а затем просто создаю новое событие, используя почти все данные из предыдущего события, а затем вызываем суперclass classа NSWindow с этим событием.

Кажется, это отлично работает для меня, и мне не пришлось даже модифицировать часть keyCode, но, возможно, это может быть проблемой …

Пример в Swift:

 class KeyInterceptorWindow : NSWindow { override func sendEvent(theEvent: NSEvent) { if theEvent.type == .KeyDown || theEvent.type == .KeyUp { println(theEvent.description) let newEvent = NSEvent.keyEventWithType(theEvent.type, location: theEvent.locationInWindow, modifierFlags: theEvent.modifierFlags, timestamp: theEvent.timestamp, windowNumber: theEvent.windowNumber, context: theEvent.context, characters: "H", charactersIgnoringModifiers: theEvent.charactersIgnoringModifiers!, isARepeat: theEvent.ARepeat, keyCode: theEvent.keyCode) super.sendEvent(newEvent!) } else { super.sendEvent(theEvent) } } 

}

  • Объектив-C Категория Причинение непризнанного селектора
  • Формирование портретной ориентации при нажатии на альбомный режим.
  • Лучший подход для синтаксического анализа XML на iPhone
  • Прокрутка UITableView внутри UIScrollView
  • Координаты текстуры OpenGL в пиксельном пространстве
  • UIPageViewController не возвращает никаких распознавателей жестов в iOS 6
  • Как отменить 2 Modal View Controllers в последовательности?
  • Позиционирование MKMapView для одновременного отображения нескольких аннотаций
  • Что делает флаг компоновщика -all_load?
  • UISlider вместе с ProgressView
  • Сохранить видео Youtube для iPhone в приложении
  • Давайте будем гением компьютера.