0

我正在使用全局键盘挂钩来使用条形码阅读器。条码阅读器在条码前面发送一个 STX 字符,在条码后面发送一个 ETX 字符。

有时 ToAscii 函数会产生正确的 STX 和 ETX 代码(0x02 或 0x03),但大多数时候它会变为 0x62 (b) 或 0x63 (c)。

这可以解释并最好解决吗?

为了清楚起见,我在下面添加了钩子回调:

    private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
    {
        if (nCode >= 0)
        {
            // Prepare the characters and retrieve the keyboard state.
            char[] characters = new char[2];
            byte[] keyState = GetKeyboardState();


            if (KeyPressed != null && WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1)
            {
                // Initialize the event arguments and fire the KeyPressed event.
                GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int)wParam);
                KeyPressed(null, e);

                // Do not call the next hook if the event has been handled.
                if (e.Handled)
                {
                    return (IntPtr)1;
                }
            }
        }

        // Call the next hook.
        return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam);
    }
}
4

2 回答 2

1

由于扫描仪是并且必须配置为 USB 键盘,因此我不得不使用低级键盘挂钩来捕获输入。但是,我现在没有使用 STX/ETX 字符作为前缀/后缀,而是将扫描仪设置为发送键盘命令(Alt + Shift + Backspace)作为前缀和后缀。

这使我可以确定条形码何时到来以及何时完成。为了防止用户意外(或有意)执行键盘命令,我实现了一个计时器。如果 100 毫秒后没有收到条形码,计时器会确保取消条形码解析。

使用 RegisterHotKey 和 UnregisterHotKey Windows API 调用捕获键盘命令。

在条码处理过程中吞下输入时,不要吞下退格字符非常重要。在热键回调之前调用低级键盘钩子,吞下退格字符将防止热键回调发生。

于 2013-11-13T13:52:03.623 回答
0

扫描仪充当键盘,但不是。

通过调用WinApi.ToAscii() 窗口将输入转换为“有效”键映射。ToAscii()将 0x02 解释为映射到“b”的键。但这将取决于当前活动安装/配置的键盘。所以仅仅依靠'b'和'c'可能会导致...俄语键盘出现问题:-)

只需使用原始输入数据,提取 STX/ETX 之间的数据并将该部分映射到 Ascii。该键码应该在lParam.vkCodeor中lParam.scanCodeKBDLLHOOKSTRUCT

结果可能如下所示,但我现在无法验证

private bool _isScanningCode;

private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
    {
        if (nCode >= 0)
        {
            // Prepare the characters and retrieve the keyboard state.
            char[] characters = new char[2];
            byte[] keyState = GetKeyboardState();

            if (lParam.scanCode == 0x02)
            {
                _isScanningCode == true;
                return (IntPtr)1; // act like key is handled
            }
            if (lParam.scanCode == 0x03)
            {
                _isScanningCode == false;
                return (IntPtr)1; //act like key is handled
            }

            if (_isScanningCode)
            {

                if (KeyPressed != null &&
                    WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1)
                {
                    // Initialize the event arguments and fire the KeyPressed event.
                    GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int) wParam);
                    KeyPressed(null, e);

                    // Do not call the next hook if the event has been handled.
                    if (e.Handled)
                    {
                        return (IntPtr) 1;
                    }
                }
            }
        }

        // Call the next hook.
        return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam);
    }
}
于 2013-11-12T15:54:23.233 回答