如何在没有NSTextView的情况下从关键事件中捕获Unicode

jls*_*ker 4 unicode cocoa nsevent

我想从应用程序的任何窗口捕获关键事件,并将它们解释为Unicode.例如,如果用户键入Option-ee(在默认配置的美国英语键盘上),我想将其识别为"é".

我尝试捕获按键事件和调用-[NSEvent characters].但是,正如文档中所述,"此方法为死键返回一个空字符串,例如Option-e." 如果我键入Option-ee,则它不会为Option-e提供任何内容,而对于第二个e则为"e" .

有没有办法将一系列密码(from -[NSEvent keyCode])组合成Unicode字符?

或者为每个键入的Unicode字符(如Java的键控事件)接收事件的方法?

jls*_*ker 10

这是一种获取一系列按键事件并获取他们键入的Unicode字符的方法.

基本上,为收到的每个按键事件调用UCKeyTranslate().使用其deadKeyState参数捕获死键并将其传递给后续调用.

例:

  • 接收Option-e的按键事件.
  • UCKeyTranslate()使用虚拟键代码(对于e),修改键状态(对于Option)和用于存储死键状态的变量进行调用.
    • UCKeyTranslate() 输出一个空字符串并更新死键状态.
  • 接收e的关键新闻事件.
  • UCKeyTranlate()使用虚拟键代码(对于e)和保持死键状态的变量进行调用.
    • UCKeyTranslate() 输出"é".

示例代码(为每个按键事件调用的函数):

/**
 * Returns the Unicode characters that would be typed by a key press.
 *
 * @param event A key press event.
 * @param deadKeyState To capture multi-keystroke characters (e.g. Option-E-E for "é"), pass a reference to the same
 *      variable on consecutive calls to this function. Before the first call, you should initialize the variable to 0.
 * @return One or more Unicode characters.
 */
CFStringRef getCharactersForKeyPress(NSEvent *event, UInt32 *deadKeyState)
{
    // http://stackoverflow.com/questions/12547007/convert-key-code-into-key-equivalent-string
    // http://stackoverflow.com/questions/8263618/convert-virtual-key-code-to-unicode-string

    TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
    CFDataRef layoutData = TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
    const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);

    CGEventFlags flags = [event modifierFlags];
    UInt32 modifierKeyState = (flags >> 16) & 0xFF;

    const size_t unicodeStringLength = 4;
    UniChar unicodeString[unicodeStringLength];
    UniCharCount realLength;

    UCKeyTranslate(keyboardLayout,
                   [event keyCode],
                   kUCKeyActionDown,
                   modifierKeyState,
                   LMGetKbdType(),
                   0,
                   deadKeyState,
                   unicodeStringLength,
                   &realLength,
                   unicodeString);
    CFRelease(currentKeyboard);
    return CFStringCreateWithCharacters(kCFAllocatorDefault, unicodeString, realLength);
}
Run Code Online (Sandbox Code Playgroud)