2011-04-26 23 views
19

我想創建一個OS X的鍵盤鉤爲輔助技術的目的(即不要擔心,不是一個鍵盤記錄)。修改NSEvent發送一個不同的密鑰比被按下

當用戶按下一個鍵,我想防止真正的按鍵和發送假的按鍵(我選擇的角色)來代替。

我有以下代碼:

- (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」來發送不同的字符。謝謝。

回答

39

你不能用NSEvent API來做到這一點,但你可以用可以CGEventTap做到這一點。您可以創建一個活動事件點擊並註冊a callback,該點接收CGEventRef,並可以對其進行修改(如有必要)並將其返回以修改實際的事件流。


編輯

這裏有一個簡單的程序,運行時,將替換所有的 「B」 鍵擊帶有 「V」:

#import <Cocoa/Cocoa.h> 

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'keystroke」,但它一直以「替換每個'v'keystroke」的形式出現。我很困惑,然後我記得我還沒有停止過應用程序)

+0

相當新的Objective-C ...幫助一些示例代碼?這與我以上的所有相似嗎? – cksubs 2011-04-26 05:02:41

+4

如果有幫助:CGEvent apis都是C.不需要objc。 – justin 2011-04-26 05:23:51

+1

@cksubs編輯答案。 – 2011-04-26 05:50:11

3

我發生在這個答案,需要做同樣的事情,但只適用於我自己的應用程序不是全球範圍內的事件。還有一個更簡單的解決方案,這個更簡單問題,我在這裏指出櫃面這對誰都有用:

  • 我攔截事件窗口,通過創建的SendEvent的覆蓋:.然後檢查關鍵事件(KeyUp或KeyDown),然後使用幾乎所有來自前置事件的數據創建新事件,然後使用此事件調用NSWindow超類。

這似乎完美地工作對我來說,我沒有,甚至修改鍵代碼的一部分 - 但也許這可能是一個問題......在斯威夫特

例子:

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) 
    } 
} 

}