GetRawInputData 在不同语言设置上嗅探字符问题

分享于2022年07月17日 .net c# keyboard-events raw-input 问答
【问题标题】:GetRawInputData 在不同语言设置上嗅探字符问题(GetRawInputData sniffing character problem on different language setting)
【发布时间】:2022-07-08 18:10:01
【问题描述】:

我正在使用 GetRawInputData 来嗅探条形码阅读器数据。 https://github.com/mfakane/rawinput-sharp

当我从条形码扫描仪读取条形码时,它通常会在 rawinput 和 pc 屏幕上获取正确的字符。下图显示了正确的场景。

GetRawInputData sniffing character problem on different language setting

我的问题是,如果我将条形码扫描仪的语言设置更改为土耳其语,rawinput 会得到如下图所示的其他字符。

GetRawInputData sniffing character problem on different language setting

如果有人以前使用过 RawInput 库,请帮助我了解为什么会发生这种情况,我需要了解如何嗅探数据,就像 pc 获取图像一样。


【解决方案1】:

我将条码扫描器的语言设置更改为土耳其

我不太明白你这是什么意思。另外我不知道您的条码扫描仪正在实施哪种 HID 设备类型。

如果我们谈论 RIM_TYPEKEYBOARD 数据(HID 使用页面 0x01,使用 ID 0x06) - 原始输入 Windows API 本身不提供任何字符。

WM_INPUT 为您提供密钥的 PS/2 扫描码(在 RAWKEYBOARD.MakeCode 中,它实际上是由 KBDHID.sys driver 从 HID Usages according to this table 转换而来)和密钥的 VK_* 代码(在 RAWKEYBOARD.VKey 字段中) .

这些印刷机可以通过调用 ToUnicode API 映射到字符。它需要作为输入 - 扫描码、vk 码和键盘状态(例如包含 CAPSLOCK 和 SHIFT 状态)。它将根据 调用者线程的活动键盘布局 进行转换。如果您需要其他键盘布局,则可以使用具有 附加参数 HKL dwhkl ToUnicodeEx

正确使用 ToUnicode / ToUnicodeEx 很棘手,因为它可能会在一次按键时发出多个字符。还有可能是死键...

但对于简单的情况,它可能是这样的:

wchar_t VkToChar(uint16_t vk, bool isShift = false)
{
    uint16_t sc = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC);
    const uint32_t flags = 1 << 2; // Do not change keyboard state of this thread

    static uint8_t state[256] = { 0 };
    state[VK_SHIFT] = isShift << 7; // Modifiers set the high-order bit when pressed

    wchar_t unicodeChar;
    if (ToUnicode(vk, sc, state, &unicodeChar, 1, flags) != 1)
        return L'\0';

    if (!std::iswprint(unicodeChar))
        return L'\0';

    return unicodeChar;
}