【问题标题】:Processing and Blocking Input from a special keyboard处理和阻止来自特殊键盘的输入
【发布时间】:2015-10-30 07:35:44
【问题描述】:

我有两个设备,一个条形码扫描仪和一个键盘,通过 USB 连接到我的 PC。我的目标是从条形码扫描仪读取所有输入并使用我的程序进行处理。此外,应该为操作系统阻止扫描仪的输入。

我找到了一篇关于这个主题的好文章,叫做: 结合 Raw Input 和键盘 Hook 来选择性地阻止来自多个键盘的输入

通过这种方法,我可以为我的程序获取输入(以及该输入来自哪个设备)并为操作系统阻止它,就像我想要的那样。但是这种方法相当复杂,因为它只适用于 inputEvents 和 Hooks 的组合。 Hooks 用于阻止操作系统的数据。 问题是无法判断 Hook 来自哪个设备。

我的问题是:有没有人知道另一种方法来阻止来自特殊键盘的输入,该键盘不适用于 inputEvents 和 Hooks 的这种组合?或者也许有可能知道 Hook 来自哪个设备?

【问题讨论】:

  • 可以将附加信息附加到窗口消息(请参阅SetMessageExtraInfo)。您是否检查了条形码扫描仪的文档以查看它是否提供了其他信息?

标签: c++ winapi raw-input keyboard-hook


【解决方案1】:

我使用 timer.tick 为 numpadkeys 创建数组并循环遍历它

GetAsyncKeyState(VK_LBUTTON) 

否则 https://msdn.microsoft.com/en-us/library/windows/desktop/ms646290(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms646298(v=vs.85).aspx

How to Check if User input is from Barcode Scanner or Keyboard?

使用 RAW Input API 相对容易。

看看“区分条码扫描仪和 WinForms 中的键盘”

我有一个程序可以读取 3 个不同的 USB 扫描仪并将输入重定向到 3 个不同的“通道”进行处理。代码有点广泛,所以我不在这里发布它。如果您愿意,我可以粘贴一些内容或通过电子邮件将项目发送给您。

作为线索是进口:

#region Raw Input API

[DllImport( "User32.dll" )]
extern static uint GetRawInputDeviceList( IntPtr pRawInputDeviceList, ref uint uiNumDevices, uint cbSize );

[DllImport( "User32.dll" )]
extern static uint GetRawInputDeviceInfo( IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize );

[DllImport( "User32.dll" )]
extern static bool RegisterRawInputDevices( RAWINPUTDEVICE[ ] pRawInputDevice, uint uiNumDevices, uint cbSize );

[DllImport( "User32.dll" )]
extern static uint GetRawInputData( IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader );

#endregion

将 InputDevice 添加到项目后,您可以通过以下方式监听事件:

// 创建一个新的 InputDevice 对象并注册 InputDevice KeyPressed 事件处理程序。

input_dev = new InputDevice( Handle );
input_dev.KeyPressed += new InputDevice.DeviceEventHandler( m_KeyPressed );

The event handler m_KeyPressed lets you to distinguish your devices through e.Keyboard.SubClass

    private void m_KeyPressed( object sender, InputDevice.KeyControlEventArgs e )
    {
        // e.Keyboard.SubClass tells you where from the event came.
        // e.Keyboard.key gives you the input data.
    }

希望有所帮助。

【讨论】:

  • 感谢您的帮助,但恐怕您的回答对我的理解来说有点短。你到底在做什么?
  • 我为 gs1 制作了一个 sscc 代码但在.net 中的条形码数据库程序
  • GetAsyncKeyState 无法区分不同的输入设备。当在计时器中使用时,它是不可靠的。由于它基于快照,因此您可能会错过键盘输入,这发生在连续采样点之间。发送键盘输入的设备通常比用户快得多。
  • 真的吗?有计时器.. 你不能像条形码扫描仪那样快速打字。输入缺失是理论,但实践表明 10 毫秒你不会错过任何数据。几天后我发布程序。因为你我的代码只有数字键盘键,这可能会被特殊键盘误导。您可以将密码数字锁推迟并完成。
  • 问题是关于从条形码扫描仪中过滤掉键盘输入。除了定时器是低优先级的消息(即几乎不会满足样本之间的 10 毫秒间隔)之外,轮询对于观察 transient 状态通常是不可靠的。另外,问题在于区分来自不同来源的键盘输入。你的回答没有解决这个问题。
【解决方案2】:

如果你阅读了我的第一个链接。

typedef struct tagINPUT_MESSAGE_SOURCE {
  INPUT_MESSAGE_DEVICE_TYPE deviceType;
  INPUT_MESSAGE_ORIGIN_ID   originId;
} INPUT_MESSAGE_SOURCE;

https://msdn.microsoft.com/en-us/library/windows/desktop/hh448799(v=vs.85).aspx POS for .NET | Differentiate between (barcode) scanner and keyboard input 来自扫描仪的数据可以用 vbcrlf 分割

http://msgroups.net/development.device.drivers/how-to-uniquely-identify-a-usb-hid/14444

【讨论】:

  • 这无法区分两个不同的 USB 设备,它们将自己注册为系统的键盘。该结构将为两个设备保存IMDT_KEYBOARDIMO_HARDWARE。并且请不要在您想添加某些内容时开始新的答案。使用您之前的答案中的edit 链接,然后更新它。
  • How do I write a good answer?。这是必读。我一次又一次地指出,你忽略了所提出的问题。您提出的任何解决方案都没有认真尝试解决这个问题。
  • 因为您的问题没有解决方案。我给你一个人们从 2003 年开始尝试的链接。就像你想要家里的电是哪一个。如果你意识到这一点,你必须同意我展示的是你能得到的最好的东西。
  • 这不是我的问题。这个问题甚至概述了一个 robust 解决方案,它恰好有点复杂(用于区分输入源的原始输入,以及用于过滤消息的键盘挂钩)。既然这已经比你提供的更好,为什么还要麻烦呢?您的任何答案都没有尝试识别输入源。这不仅仅是一些不错的功能,而是一项核心要求。
猜你喜欢
  • 1970-01-01
  • 2012-10-04
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
相关资源
最近更新 更多