如何区分C#中的多个input设备
我有一个条形码扫描器(就像一个键盘),当然我也有一个键盘连接到电脑。 该软件正在接受来自扫描仪和键盘的input。 我只需要接受扫描仪的input。 代码是用C#编写的。 有没有办法“禁用”从键盘input,只接受来自扫描仪的input?
注:键盘是笔记本电脑的一部分…所以不能拔掉。 此外,我试着把下面的代码保护重写布尔ProcessDialogKey(System.Windows.Forms.Keys keyData){返回true; }但是,随着忽略键盘上的按键,条形码扫描仪input也被忽略。
我不能让扫描仪发送正面字符,扫描仪正在被其他应用程序使用,添加正面字符stream将意味着修改其他代码。
另外,由于扫描的条形码可能是单字符条形码,因此我不能使用计时方法来确定input是否来自条形码扫描仪(如果是一串字符后跟暂停)。
是的,我正在读取stream中的数据。
我试图按照文章:在WinForms的键盘区分条码扫描仪。 不过,我有以下问题:
- 由于其保护级别,我收到一个错误,NativeMethods无法访问。 好像我需要导入一个dll; 它是否正确? 如果是这样,我该怎么做?
- 我应该使用哪个保护覆盖void WndProc(ref Message m)定义,文章中有两个实现?
- 获取与[SecurityPermission(SecurityAction.LinkDemand,Flags = SecurityPermissionFlag.UnmanagedCode)]错误相关的错误CS0246:无法findtypes或名称空间名称“SecurityPermission”(缺lessusing指令或程序集引用吗? 我该如何解决这个错误?
- 包含以下内容的行也有错误:if((从hardwareIds中的hardwareId中,deviceName.Contains(hardwareId)selecthardwareId).Count()> 0)错误是错误CS1026:)。
- 我应该把文章中的所有代码放在一个名为BarcodeScannerListener.cs的.cs文件中吗?
Nicholas Piasecki在http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/上发布的有关C#解决scheme源代码的后续问题:
- 我无法在VS 2005中打开解决scheme,因此我下载了Visual C#2008 Express Edition,并且运行了代码。 然而,连接我的条形码扫描器和扫描条形码后,程序不能识别扫描。 我在OnBarcodeScanned方法中放了一个断点,但是它从来没有被打中。 我确实使用设备pipe理器获取的条码扫描器的ID来更改App.config。 似乎有2个devicename与HID#Vid_0536&Pid_01c1(从扫描仪连接时从设备pipe理器获得)。 我不知道这是否导致扫描不起作用。 遍历deviceNames时,下面是我find的设备列表(使用debugging器):
“\ ?? \ HID#Vid_0536&Pid_01c1&#MI_01 9 25ca5370&0&#0000 {4d1e55b2-F16F-11CF-88cb-001111000030}”
“\ ?? \ HID#Vid_0536&Pid_01c1&#MI_00 9 38e10b9&0&#0000 {884b96c3-56ef-11D1-bc8c-00a0c91405dd}”
“\ ?? \ HID#Vid_413c&Pid_2101&MI_00#8&1966e83d&0&#0000 {884b96c3-56ef-11D1-bc8c-00a0c91405dd}”
“\ ?? \ HID#Vid_413c&Pid_3012#7&960fae0&0&#0000 {378de44c-56ef-11D1-bc8c-00a0c91405dd}”
“\ ?? \ Root#RDP_KBD#0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}”“\ ?? \ ACPI#PNP0303#4&2f94427b&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}”“\? \ Root#RDP_MOU#0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}“”\ ?? \ ACPI#PNP0F13#4&2f94427b&0#{378de44c-56ef-11d1-bc8c-00a0c91405dd}“
所以有2个条目为HID#Vid_0536&Pid_01c1; 可能导致扫描不起作用?
好吧,似乎我必须找出一种方法,不依赖于由扫描仪发送的ASCII 0x04字符…因为我的扫描仪不发送该字符。 之后,条形码扫描事件被激活,并显示条形码popup。 所以谢谢Nicholas的帮助。
您可以使用Raw Input API来像最近一样区分键盘和扫描仪。 不pipe你连接了多less个键盘或类似键盘的设备, 在按键映射到通常在KeyDown
事件中看到的与设备无关的虚拟键之前,您将看到一个WM_INPUT
。
更容易的是做别人推荐的东西,configuration扫描仪在条形码前后发送哨兵字符。 (通常通过扫描扫描仪用户手册后面的特殊条形码来完成此操作。)然后,如果主窗体的KeyPreview
事件处于读取条形码的中间,则可以看到这些卷动结束并吞下任何子控件的按键事件。 或者,如果你想更有趣,可以使用SetWindowsHookEx()
的低级键盘钩子来监视那些哨兵并将它们吞下去(这样做的好处是即使你的应用程序没有,也可以得到事件焦点)。
我无法改变我们的条码扫描仪的哨兵价值,所以我不得不走上复杂的路线。 绝对是痛苦的 保持简单,如果你可以!
–
七年后的更新:如果您的使用案例是从USB条形码扫描仪读取的,Windows 10在Windows.Devices.PointOfService.BarcodeScanner
内置了一个友好的API。 这是一个UWP / WinRT API,但是您也可以在普通的桌面应用程序中使用它; 这就是我现在正在做的事情。 下面是一些示例代码,直接从我的应用程序,给你的要点:
{ using System; using System.Linq; using System.Threading.Tasks; using System.Windows; using Windows.Devices.Enumeration; using Windows.Devices.PointOfService; using Windows.Storage.Streams; using PosBarcodeScanner = Windows.Devices.PointOfService.BarcodeScanner; public class BarcodeScanner : IBarcodeScanner, IDisposable { private ClaimedBarcodeScanner scanner; public event EventHandler<BarcodeScannedEventArgs> BarcodeScanned; ~BarcodeScanner() { this.Dispose(false); } public bool Exists { get { return this.scanner != null; } } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } public async Task StartAsync() { if (this.scanner == null) { var collection = await DeviceInformation.FindAllAsync(PosBarcodeScanner.GetDeviceSelector()); if (collection != null && collection.Count > 0) { var identity = collection.First().Id; var device = await PosBarcodeScanner.FromIdAsync(identity); if (device != null) { this.scanner = await device.ClaimScannerAsync(); if (this.scanner != null) { this.scanner.IsDecodeDataEnabled = true; this.scanner.ReleaseDeviceRequested += WhenScannerReleaseDeviceRequested; this.scanner.DataReceived += WhenScannerDataReceived; await this.scanner.EnableAsync(); } } } } } private void WhenScannerDataReceived(object sender, BarcodeScannerDataReceivedEventArgs args) { var data = args.Report.ScanDataLabel; using (var reader = DataReader.FromBuffer(data)) { var text = reader.ReadString(data.Length); var bsea = new BarcodeScannedEventArgs(text); this.BarcodeScanned?.Invoke(this, bsea); } } private void WhenScannerReleaseDeviceRequested(object sender, ClaimedBarcodeScanner args) { args.RetainDevice(); } private void Dispose(bool disposing) { if (disposing) { this.scanner = null; } } } }
当然,你需要一个支持USB HID POS的条码扫描器,而不仅仅是一个键盘楔子。 如果您的扫描仪只是一个键盘楔子,我build议像$ 25一样拿起一个像eBay上使用的Honeywell 4600G一样的东西。 相信我,你的理智是值得的。
我在类似情况下所做的是通过查看input的速度来区分扫描和用户打字。
很多字符非常接近,然后暂停就是扫描。 其他任何东西都是键盘input。
我不知道你的要求,所以也许这不会为你做,但这是我得到的最好的:)
这取决于您与设备进行交互的方式。 无论如何,它不会是一个C#解决scheme,它会是一些其他的图书馆。 你正在读取数据stream? 如果你只是按键,可能没有什么可以做的。
我已经成功地完成了你们在这里寻找的东西。 我有一个应用程序,可以从Honeywell / Metrologic条形码扫描器接收所有条形码字符数据。 系统上没有其他应用程序从扫描仪接收数据,键盘继续正常工作。
我的应用程序使用原始input和可怕的低级键盘挂钩系统的组合。 与此处所写的相反,我发现wm_input消息是在调用键盘钩子函数之前收到的。 我处理wm_input消息的代码基本上设置了一个布尔variables来指定接收到的字符是否来自扫描器。 在处理完wm_input之后立即调用的键盘挂钩函数会吞服扫描器的伪键盘数据,从而阻止其他应用程序接收数据。
键盘挂钩function必须放在一个dll,因为你想拦截所有的系统键盘消息。 此外,内存映射文件必须用于wm_input处理代码与dll进行通信。
看看这个: http : //nate.dynalias.net/dev/keyboardredirector.rails ( NOT AVAILABLE ANYMORE )很好用!
指定您想要阻止的键盘和键,它就像一个魅力!
我认为你可能能够通过DirectX API区分多个键盘,或者如果这不起作用,可以通过原始inputAPI。
我知道这是一个古老的线程,通过在WIN10中search条形码扫描find它。 只是几个笔记,以防有人需要它。
霍尼韦尔的这些扫描仪有几个USB接口。 一个是键盘+ Hid销售点(复合设备)。 还有CDC-ACM(ComPort仿真)和Hid Point of sales(单独)+更多。
默认情况下,扫描仪暴露一个序列号,所以主机可以区分很多设备(我曾经有+20次连接)。 有一个命令来禁用序列号!
较新的型号在这方面performance相同。 如果你想看到它,试试我的terminal程序yat3(免费在我的网站上 )。 它可以打开上面提到的所有接口,并为这些设备量身打造。
一个字使用键盘接口:
只能用它们作为最后的手段。 当涉及到异国情调的人物时,他们很慢,不太可靠。 唯一有用的是如果你想input数据到现有的应用程序。 如果您仍然编码,那么从ComPort / HidPos-Device读取更容易。