1

在一个 winforms 应用程序中,我需要从标准 USB 条形码扫描仪读取输入,该扫描仪使自身显示为 Windows 的 USB 键盘。这必须在不关注特定控件的情况下工作(即,我不能说“单击此文本框然后扫描条形码”)。扫描器被配置为向它扫描的每个代码输出一个标题和尾部。

我宁愿不采用“原始”方式,即直接连接到 USB 输入或 Windows 事件(WM_INPUT 等)。

我当然可以在 ProcessCmdKey 中捕获击键,但是我似乎无法正确识别标题/预告片的键(分别为 ^~{ 和 }~^)。

知道如何在托管代码中正确完成此操作吗?

4

3 回答 3

3

这有效,但有点难看:

    [DllImportAttribute("User32.dll")]
    public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpChar, int uFlags);

    [DllImportAttribute("User32.dll")]
    public static extern int GetKeyboardState(byte[] pbKeyState);

    public static char GetAsciiCharacter(int uVirtKey, int uScanCode)
    {
        byte[] lpKeyState = new byte[256];
        GetKeyboardState(lpKeyState);
        byte[] lpChar = new byte[2];
        if (ToAscii(uVirtKey, uScanCode, lpKeyState, lpChar, 0) == 1)
            return (char)lpChar[0];
        else
            return new char();
    }

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if(keyData == Keys.ShiftKey || keyData == Keys.Shift)
            return base.ProcessCmdKey(ref msg, keyData);

        char keyChar = GetAsciiCharacter((int) (keyData & Keys.KeyCode), (((int) msg.LParam) & 0x1000000));

        if(keyChar == '\0')
            return base.ProcessCmdKey(ref msg, keyData);

        _currentSequence.Add(keyChar);

        if (_currentSequence.ToString() == "^~{")
        {
            _handlingInputFromScanner = true;
            _scannerBuffer.Clear();
            return true;
        }

        if (_currentSequence.ToString() == "}~^")
        {
            _handlingInputFromScanner = false;
            OnScannerRead.Invoke(this, new ScannerReadEventArgs { ScannerData = _scannerBuffer.ToString() });
            _scannerBuffer.Clear();
            return true;
        }

        if (keyChar == '}' || keyChar == '{' || keyChar == '~' || keyChar == '^')
        {
            return true;
        }

        if (_handlingInputFromScanner)
        {
            _scannerBuffer.Append(keyChar);
            return true;
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }
于 2010-12-16T22:24:46.613 回答
0

ProcessCmdKey 是执行此操作的正确位置。

于 2010-12-16T18:29:07.113 回答
0

可能是一个被面板隐藏的文本框,当要扫描条形码时获得焦点,然后使用 keydown 事件,这应该可以让您获得扫描仪发送的字符的原始 ascii 值

于 2010-12-16T18:29:32.027 回答