阻止来自键盘HID的输入

时间:2013-11-18 13:31:51

标签: c# wpf barcode-scanner hid

我正在将USB条形码扫描仪的支持集成到WPF应用程序中,但我遇到了麻烦。

目前,我已在this文章的帮助下成功识别和捕获输入。

我面临的问题是虽然我成功识别并路由来自扫描仪设备的输入,但我无法阻止输入事件以进行进一步处理(例如,如果我的应用程序上的文本框控件具有输入焦点,输入从扫描仪将写入它。)

我尝试了两种捕获输入的方法:

var wndSourceHandle = HwndSource.FromHwnd(new WindowInteropHelper(
                                          _wndEventSource = value).Handle);
wndSourceHandle.AddHook(this.WndProc);

WndProc定义:

private IntPtr WndProc(IntPtr hwnd, int iMessage, IntPtr wParam, IntPtr lParam, ref  bool bisHandled)
    {
        if (iMessage == Win32.WM_INPUT)
        {
            var result = ProcessRawInput(lParam);
            bisHandled = result != null && result.Value;
            return IntPtr.Zero;
        }

        return IntPtr.Zero;
    }

以及:

ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) =>
                {
                    if (msg.message == Win32.WM_INPUT)
                    {
                        var result = ProcessRawInput(msg.lParam);
                        handled = result != null && result.Value;
                        return;
                    }

                    handled = false;
                };

如果输入源是条形码扫描器,则ProcessRawInput方法返回true,否则返回false。

2 个答案:

答案 0 :(得分:2)

经过一番研究后,我找到了适用于WinForms here的解决方案。我能够为WPF修改它,如下所示:

ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) =>
                {
                    if (msg.message == Win32.WM_INPUT)
                    {
                        var result = ProcessRawInput(msg.lParam);
                        this.m_bIgnoreNextKeyDownMessage = result != null && result.Value;
                        return;
                    }
                    if (msg.message == Win32.WM_KEYDOWN && this.m_bIgnoreNextKeyDownMessage)
                    {
                        handled = true;
                    }

                    this.m_bIgnoreNextKeyDownMessage = false;
                };

此解决方案基本上将条形码WM_INPUT消息后的第一条WM_KEYDOWN消息标记为“已处理”。我不确定这是否是唯一/最好/最安全的解决方案,但它看起来就像是诀窍。

<强>更新

通过上述解决方案,我仍然发现每次扫描条形码中的一个随机字符都会滑到一个聚焦文本框 - 我不知道为什么会这样 - 可能是键盘事件的时间问题它们通过消息处理程序传递。检查是否应忽略WM_KEYDOWN消息的另一种解决方案:

if (msg.message == Win32.WM_KEYDOWN && !String.IsNullOrEmpty(this.m_strKeyInput))
{
    handled = true;
}

缓冲区m_strKeyInput包含当前扫描的条形码值 - 当没有条形码可用时,此缓冲区为空,条形码扫描器按下条形码时一次构建一个字符 - 然后在生成自定义BarcodeScanned事件后清空。我能想到的这个解决方案的唯一缺点就是所有键盘都会在从扫描仪中推出条形码的几毫秒内停止运行 - 这对我的情况来说是可以接受的。

答案 1 :(得分:0)

听起来好像是您将扫描仪的输入路由(将其视为键盘)和文本框,您只需使用该文本框中的一个Preview *事件即可执行其他处理。例如,您可以覆盖PreviewTextInput

private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
  // MyBarcodeScanner would be a reference to the IInput device that represents the scanner:
  if (e.Device == MyBarcodeScanner)
  {
    // Process the text, rejecting it in this case.
    // Marking the event as handled will prevent the 'TextChanged' event 
    // from firing, so the characters will not appear in the text box.
    e.Handled = true;
  }
  else
  {
    // This is some other keyboard, by not handling the event,
    // the users will be allowed to enter text normally.
  }
}

您可能需要做一些试验和错误,以弄清楚如何识别由'e.Device'识别的条形码扫描仪,但这应该相对容易。对不起,我不能完整,但我没有自己的条形码扫描仪来试验。