如何在没有NSTextView的情况下从关键事件中捕获Unicode [英] How to capture Unicode from key events without an NSTextView

查看:123
本文介绍了如何在没有NSTextView的情况下从关键事件中捕获Unicode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我尝试捕获按键事件并调用-[NSEvent characters].但是,如文档中所述,此方法为空键返回空字符串,例如Option-e."如果我键入 Option-ee ,那么对于 Option-e 它没有任何帮助,而对于第二个 e 则为普通的"e". >

是否可以将一系列键码(来自-[NSEvent keyCode])组合成Unicode字符?

或者一种为每个键入的Unicode字符接收事件的方式(例如 Java的键类型事件)?

解决方案

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

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

示例:

  • 接收 Option-e 的按键事件.
  • 使用虚拟键代码(对于 e ),修饰键状态(对于 Option )和用于存储死键状态的变量调用UCKeyTranslate().
    • UCKeyTranslate()输出一个空字符串并更新死键状态.
  • 接收 e 的按键事件.
  • 使用虚拟键代码(用于 e )和保存死键状态的变量调用UCKeyTranlate().
    • 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);
}

I'd like to capture key events from any window in the application and interpret them as Unicode. For example, if the user types Option-e-e (on a default-configured US English keyboard), I would like to recognize that as "é".

I tried capturing keypress events and calling -[NSEvent characters]. However, as it says in the documentation, "This method returns an empty string for dead keys, such as Option-e." If I type Option-e-e, then it gives me nothing for the Option-e and plain "e" for the second e.

Is there a way to combine a series of keycodes (from -[NSEvent keyCode]) into a Unicode character?

Or a way to receive an event for each Unicode character typed (like Java's key-typed event)?

解决方案

Here's a way to take a series of key press events and get the Unicode character(s) they'd type.

Basically, call UCKeyTranslate() for each key press event received. Use its deadKeyState argument to capture a dead key and pass it along to the subsequent call.

Example:

  • Receive key press event for Option-e.
  • Call UCKeyTranslate() with the virtual key code (for e), the modifier key state (for Option), and a variable to store the dead key state.
    • UCKeyTranslate() outputs an empty string and updates the dead key state.
  • Receive key press event for e.
  • Call UCKeyTranlate() with the virtual key code (for e) and the variable that holds the dead key state.
    • UCKeyTranslate() outputs "é".

Sample code (the function to call for each key press event):

/**
 * 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);
}

这篇关于如何在没有NSTextView的情况下从关键事件中捕获Unicode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆