处理 USB 条码扫描仪充当键盘,并在表单上的任何位置提供页眉/拖尾

发布于 2024-10-07 20:09:42 字数 304 浏览 2 评论 0原文

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

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

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

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

In a winforms app, I need to read input from a standard USB barcode scanner, one which makes iteself appears as a USB keyboard to windows. This has to work without giving focus to a particular control (ie, I can't say "click on this textbox then scan the barcode"). The scanner is configured to output a header and trailer to every codes it scans.

I'd rather don't go the "raw" way, ie, hooking directly into the USB input or Windows events (WM_INPUT and such).

I can of course trap the keystrokes in ProcessCmdKey, but then I don't seem to be able to properly identify the keys for the header/trailer (^~{ and }~^ respectively).

Any idea how this can be done properly in managed code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼睛会笑 2024-10-14 20:09:42

这可行,但有点难看:

    [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);
    }

This works, but it's kinda ugly:

    [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);
    }
我恋#小黄人 2024-10-14 20:09:42

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

ProcessCmdKey is the right place to do it.

肩上的翅膀 2024-10-14 20:09:42

也许是一个被面板隐藏的文本框,在扫描条形码时获得焦点,然后使用 keydown 事件,这应该会得到扫描仪发送的字符的原始 ascii 值

maybe a textbox hidden by a panel, that gets focus when the barcode is to be scanned, and then use the keydown event, that should get you the raw ascii values of the characters sent by the scanner

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文