一尘不染

如何在C#中区分多个输入设备

c#

我有一台条形码扫描仪(起着键盘的作用),当然我的键盘也挂在计算机上了。该软件正在接受扫描仪和键盘的输入。我只需要接受扫描仪的输入。该代码用C#编写。有没有一种方法可以“禁用”键盘输入并仅接受来自扫描仪的输入?

注意:键盘是笔记本电脑的一部分…因此无法拔出。另外,我尝试将以下代码保护为覆盖的值Boolean
ProcessDialogKey(System.Windows.Forms.Keys keyData){return true;
}但是,除了忽略键盘的击键操作外,条形码扫描器的输入也将被忽略。

我无法让扫描程序发送标记字符,因为其他应用程序正在使用该扫描器,添加标记字符流将意味着修改其他代码。

另外,由于扫描的条形码可能是单字符条形码,因此我无法使用确定输入是否来自条形码扫描仪的计时方法(如果输入的是一堆字符,然后是暂停)。

是的,我正在从流中读取数据。

我正在尝试遵循以下文章:从WinForms中的键盘区分条形码扫描仪。但是我有以下问题:

  1. 我收到一个错误,因为其保护级别,NativeMethods无法访问。好像我需要导入一个dll。它是否正确?如果是这样,我该怎么办?
  2. 我应该使用哪个受保护的重写void WndProc(ref Message m)定义,本文中有两种实现?
  3. 正在收到与[SecurityPermission(SecurityAction.LinkDemand,Flags = SecurityPermissionFlag.UnmanagedCode)]相关的错误CS0246:找不到类型或名称空间名称’SecurityPermission’(您是否缺少using指令或程序集引用?)。如何解决此错误?
  4. 在包含以下内容的行上也存在错误:if((从hardwareIds中的hardwareId,其中deviceName.Contains(hardwareId)选择hardwareId).Count()> 0)错误是错误CS1026:)。
  5. 我是否应该将文章中的所有代码放在一个名为BarcodeScannerListener.cs的.cs文件中?

Nicholas Piasecki在http://nicholas.piasecki.name/blog/2009/02/distinguishing-
barcode-scanners-from-the-keyboard-in-
winforms/上发布的有关C#解决方案源代码的后续问题:

  1. 我无法在VS 2005中打开该解决方案,因此我下载了Visual C#2008 Express Edition,并运行了代码。但是,在连接我的条形码扫描仪并扫描条形码后,程序无法识别扫描。我在OnBarcodeScanned方法中设置了一个断点,但是它从未被击中。我确实使用通过设备管理器获取的条形码扫描仪的ID更改了App.config。似乎有2个具有HID#Vid_0536&Pid_01c1的设备名(在连接扫描仪时从设备管理器获取)。我不知道这是否导致扫描不起作用。遍历deviceNames时,这是我找到的设备列表(使用调试器):

“ \ ?? \
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}”

因此,对于HID#Vid_0536&Pid_01c1,有2个条目;那会导致扫描不起作用吗?

好的,所以看来我不得不找出一种不依赖于扫描程序发送的ASCII
0x04字符的方法…因为我的扫描程序不发送该字符。之后,将触发条形码扫描事件,并显示带有条形码的弹出窗口。因此,感谢尼古拉斯的帮助。


阅读 890

收藏
2020-05-19

共1个答案

一尘不染

您可以像我最近一样使用Raw Input
API区分键盘和扫描仪。
连接了多少个键盘或类似键盘的设备都没有关系;您将WM_INPUT在击键映射到通常在KeyDown事件中通常看到的与设备无关的虚拟键之前看到一个。

执行其他人推荐的操作和配置扫描仪以在条形码前后发送哨兵字符要容易得多。(您通常可以通过扫描扫描仪用户手册背面的特殊条形码来进行此操作。)然后,主窗体的KeyPreview事件可以监视那些滚动结束并吞下任何子控件的关键事件(如果该控件处于读取条形码的中间)。或者,如果您想成为更高级的爱好者,则可以使用低级键盘钩SetWindowsHookEx()来监视那些哨兵并将其吞入那里(这样做的好处是,即使您的应用程序没有关注焦点,您仍然可以得到该事件)。

除其他外,我无法更改条形码扫描器上的哨兵值,因此我不得不走复杂的路线。绝对是痛苦的。如果可以,请保持简单!

-

七年后的更新: 如果您的用例是从USB条码扫描器读取的,则Windows 10具有一个内置的友好,友好的API
Windows.Devices.PointOfService.BarcodeScanner。它是一个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的条形码扫描仪,而不仅仅是键盘楔。如果您的扫描仪只是一个键盘楔子,我建议您以25美元的价格在eBay上购买二手Honeywell
4600G。相信我,您的理智是值得的。

2020-05-19