将虚拟键码转换为Unicode字符串

9
我有一些代码,用于获取当前键盘布局并将虚拟键码转换为字符串。在大多数情况下这很有效,但我在某些特定情况下遇到了麻烦。让我注意到这个问题的是德语QWERTZ键盘上退格键旁边的重音键。 http://en.wikipedia.org/wiki/File:KB_Germany.svg 该键生成我期望的VK代码kVK_ANSI_Equal,但在使用QWERTZ键盘布局时,我没有得到任何描述。它最终成为一个死键,因为它应该与另一个键组合。有没有办法捕获这些情况并进行适当的转换?
我的当前代码如下。
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);

if(keyboardLayout)
{
    UInt32 deadKeyState = 0;
    UniCharCount maxStringLength = 255;
    UniCharCount actualStringLength = 0;
    UniChar unicodeString[maxStringLength];

    OSStatus status = UCKeyTranslate(keyboardLayout,
                                     keyCode, kUCKeyActionDown, 0,
                                     LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
                                     &deadKeyState,
                                     maxStringLength,
                                     &actualStringLength, unicodeString);

    if(actualStringLength > 0 && status == noErr)
        return [[NSString stringWithCharacters:unicodeString length:(NSInteger)actualStringLength] uppercaseString];
}

1
你应该设置kUCKeyTranslateNoDeadKeysMask而不是kUCKeyTranslateNoDeadKeysBit,因为后者被定义为0,而前者是一个掩码,实际上启用了该位。 - rdb
1个回答

14

如你亲自试验或查看激活德语布局的键盘查看器所示,该键是一个死键。

在Mac上,输入死键的实际字符而不与另一个字符组合的方法是在其后按空格。所以请尝试:关闭kUCKeyTranslateNoDeadKeysBit,如果UCKeyTranslate设置了死键状态,则将其后的空格进行转换。

编辑(由提问者添加)

仅供未来参考,这是经过修正并拥有正确解决方案的代码。

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

if(keyboardLayout)
{
    UInt32 deadKeyState = 0;
    UniCharCount maxStringLength = 255;
    UniCharCount actualStringLength = 0;
    UniChar unicodeString[maxStringLength];

    OSStatus status = UCKeyTranslate(keyboardLayout,
                                     keyCode, kUCKeyActionDown, 0,
                                     LMGetKbdType(), 0,
                                     &deadKeyState,
                                     maxStringLength,
                                     &actualStringLength, unicodeString);

    if (actualStringLength == 0 && deadKeyState)
    {
        status = UCKeyTranslate(keyboardLayout,
                                         kVK_Space, kUCKeyActionDown, 0,
                                         LMGetKbdType(), 0,
                                         &deadKeyState,
                                         maxStringLength,
                                         &actualStringLength, unicodeString);   
    }
    if(actualStringLength > 0 && status == noErr)
        return [[NSString stringWithCharacters:unicodeString length:(NSUInteger)actualStringLength] uppercaseString];
}

这段代码是用于键绑定翻译的。以便在此上下文之外可以使用该键。我正在HID级别上获取它,但我需要一种方法来向用户显示绑定的键是什么。如何告诉用户,在QWERTZ布局中,虚拟键是哪个键帽? - Joshua Weinberg
这是修复后的代码,非常感谢Peter,https://github.com/OpenEmu/OpenEmu/commit/a59dddfa669ab0e2872f79a6443c45e2a2d87253 - Joshua Weinberg
@JoshuaWeinberg:我已经纠正了你添加到我的答案中的代码;你将长度转换为了错误的类型。 - Peter Hosey
3
注意:在原帖中,由于错误使用,kUCKeyTranslateNoDeadKeysBit一开始并没有被打开。传递kUCKeyTranslateNoDeadKeysBit或0之间没有区别,因为前者定义为0。设置了该位的实际掩码为kUCKeyTranslateNoDeadKeysMask。 - rdb
太棒了。谢谢彼得! - Terminality

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接