.NET 的 POS |区分(条形码)扫描仪和键盘输入

Posted

技术标签:

【中文标题】.NET 的 POS |区分(条形码)扫描仪和键盘输入【英文标题】:POS for .NET | Differentiate between (barcode) scanner and keyboard input 【发布时间】:2011-07-12 16:30:10 【问题描述】:

我想在 WPF 应用程序中区分(条形码)扫描仪和键盘输入。 我需要的是一个在我的扫描仪提供数据时发生的事件。

在我的应用程序中,有一个特殊字段将填充来自扫描仪的输入。所以,如果用户关注了另一个领域,我不想在其中插入扫描的代码,而是我的特殊领域。

首先,我将扫描仪(通过 USB 连接)的输入模式从“键盘模拟”切换为“原始”。但是我现在需要做什么?

【问题讨论】:

简单的解决方案..有一个下拉列表,手动或自动,默认设置为自动。当进行手动键盘输入时,让人员切换它。 即使焦点不在目标文本框上,是否有办法从指定的 USB 条码扫描仪读取数据?可以通过指定产品和供应商ID来完成吗? @FrEEzE2046 我在你的上一篇文章中阅读了你的代码,但是我还不知道它是否涵盖了我上面提到的内容。请帮我驱散这周围的迷雾。如果它确实回答了我的问题,您能否就我的应用程序如何使用您的代码给我一些指导?谢谢!!问候 【参考方案1】:

实现 OPOS 或 WEPOSWEB 内容不再可用)的扫描程序具有包装设备驱动程序的 COM 和/或 .Net 组件。这些组件可以在扫描数据时引发事件。这些标准还适用于更多领域,包括磁条阅读器、秤、钱箱、零钱机和 MICR(支票)阅读器。

如果未提供 xPOS 驱动程序,您可能会获得 USB/串行端口驱动程序。这使设备看起来像是通过 rs232 连接到 windows。然后您可以使用System.IO.Ports.SerialPort 编写一个“扫描仪”抽象。

另一种选择是获取 .sys 和 .h 文件。然后你正在做一些相关的 PInvoke,可能还有一些 C。

【讨论】:

我的扫描仪有一个 OPOS 驱动程序。我坚信我可以通过使用 POS for .NET 来实现这一点,但不知道如何识别我的扫描仪。【参考方案2】:

我已经放弃了使用 POS for .NET 实现这一点的方法。自己做几乎更容易,因为扫描仪处理它是您感兴趣的框架的唯一相关部分。这基本上是我正在使用的:

public class RawInput

    private static IntPtr DispatchMessage(IntPtr lParam, IEnumerable<IntPtr> fromDevices, ref object data)
    
        var dataSize = UIntPtr.Zero;
        if (Win32.GetRawInputData(lParam, (UIntPtr)CommandFlag.Input, IntPtr.Zero, ref dataSize, (UIntPtr)Marshal.SizeOf(typeof(Win32.RAWINPUTHEADER))) == UIntPtr.Zero)
        
            var buff = Marshal.AllocHGlobal((int)dataSize);
            var outSize = Win32.GetRawInputData(lParam, (UIntPtr)CommandFlag.Input, buff, ref dataSize, (UIntPtr)Marshal.SizeOf(typeof(Win32.RAWINPUTHEADER)));

            Debug.Assert(outSize == dataSize);
            var input = (Win32.RAWINPUT)Marshal.PtrToStructure(buff, typeof(Win32.RAWINPUT));

            var hDevice = IntPtr.Zero;
            if (fromDevices == null)
                hDevice = input.header.hDevice;
            else
                hDevice = fromDevices.FirstOrDefault(h => h == input.header.hDevice);

            if (hDevice != IntPtr.Zero)
            
                switch ((Type)input.header.dwType)
                
                    case Type.HID:
                        var hidData = new HIDDATA()
                        
                            count = input.hid.dwCount,
                            size = input.hid.dwSizeHid,
                            raw = new byte[input.hid.dwCount * input.hid.dwSizeHid]
                        ;

                        Marshal.Copy(
                            new IntPtr(
                                buff.ToInt64() +
                                Marshal.SizeOf(typeof(Win32.RAWINPUTHEADER)) +
                                Marshal.SizeOf(typeof(Win32.RAWHID))
                            ),
                            hidData.raw, 0, hidData.raw.Length
                        );

                        data = hidData;
                        break;
                    case Type.Keyboard:
                        data = new KEYBOARDDATA
                        
                            makeCode = input.keyboard.MakeCode,
                            flags = (KeyboardFlag)input.keyboard.Flags,
                            vKey = input.keyboard.VKey,
                            message = (MessageContext)input.keyboard.Message,
                            extraInfo = input.keyboard.ExtraInformation
                        ;
                        break;
                    case Type.Mouse:
                        var mouseData = new MOUSEDATA
                        
                            extraInfo = input.mouse.ulExtraInformation,
                            flags = (MouseFlag)input.mouse.usFlags,
                            transitions = (MouseTransition)input.mouse.usButtonFlags,
                            motionX = input.mouse.lLastX,
                            motionY = input.mouse.lLastY
                        ;

                        if (mouseData.transitions == MouseTransition.MouseWheel)
                            mouseData.wheelDelta = input.mouse.usButtonData;
                        data = mouseData;
                        break;
                
            

            Marshal.FreeHGlobal(buff);
            return hDevice;
        
        else
            throw new ApplicationException("An error occurred while receiving raw input data.");
    

    public static bool DispatchMessage(Win32.MSG message, IEnumerable<Device> fromDevices, ref Device source, ref object data)
    
        var hDevice = IntPtr.Zero;
        if (message.message == MessageContext.Input)
        
            if (fromDevices != null)
            
                hDevice = DispatchMessage(message.lParam, fromDevices.Select(h => h.Handle), ref data);
                if (hDevice != IntPtr.Zero)
                    source = fromDevices.First(h => h.Handle == hDevice);
            
            else
            
                Func<Device> getRawInputDeviceInfo = () =>
                
                    var name_size = UIntPtr.Zero;
                    Win32.GetRawInputDeviceInfo(hDevice, (UIntPtr)Win32.RIDI_DEVICENAME, IntPtr.Zero, ref name_size);

                    if (name_size != UIntPtr.Zero)
                    
                        var name = Marshal.AllocHGlobal((int)name_size);
                        Win32.GetRawInputDeviceInfo(hDevice, (UIntPtr)Win32.RIDI_DEVICENAME, name, ref name_size);
                        string rid_name = (string)Marshal.PtrToStringAnsi(name);

                        var ridSize = (UIntPtr)Marshal.SizeOf(typeof(Win32.RID_DEVICE_INFO));
                        var buff = Marshal.AllocHGlobal((int)ridSize);
                        var outSize = Win32.GetRawInputDeviceInfo(hDevice, (UIntPtr)Win32.RIDI_DEVICEINFO, buff, ref ridSize);
                        Debug.Assert(outSize == ridSize);

                        var rid = (Win32.RID_DEVICE_INFO)Marshal.PtrToStructure(buff, typeof(Win32.RID_DEVICE_INFO));

                        var device = new Device()
                        
                            Handle = hDevice,
                            ID = rid_name,
                            Type = (Type)rid.dwType,
                            Description = GetRawInputDeviceDescription(rid_name)
                        ;

                        Marshal.FreeHGlobal(name);
                        return device;
                    

                    return null;
                ;

                hDevice = DispatchMessage(message.lParam, null, ref data);
                if (hDevice != IntPtr.Zero)
                    source = getRawInputDeviceInfo();
            
        

        return hDevice != IntPtr.Zero;
    

    public static IEnumerable<Device> EnumerateDevices()
    
        var ridSize = (UIntPtr)Marshal.SizeOf(typeof(Win32.RAWINPUTDEVICELIST));
        var ridCnt = UIntPtr.Zero;
        var list = new List<Device>();

        if (Win32.GetRawInputDeviceList(IntPtr.Zero, ref ridCnt, ridSize) == UIntPtr.Zero)
        
            var buff = Marshal.AllocHGlobal((int)ridCnt * (int)ridSize);
            Win32.GetRawInputDeviceList(buff, ref ridCnt, ridSize);

            for (int i = 0; i < (int)ridCnt; ++i)
            
                var rid = (Win32.RAWINPUTDEVICELIST)Marshal.PtrToStructure(
                    new IntPtr((buff.ToInt64() + (int)ridSize * i)),
                    typeof(Win32.RAWINPUTDEVICELIST)
                );

                var nameSize = UIntPtr.Zero;
                Win32.GetRawInputDeviceInfo(rid.hDevice, (UIntPtr)Win32.RIDI_DEVICENAME, IntPtr.Zero, ref nameSize);

                if (nameSize != UIntPtr.Zero)
                
                    var name = Marshal.AllocHGlobal((int)nameSize);
                    Win32.GetRawInputDeviceInfo(rid.hDevice, (UIntPtr)Win32.RIDI_DEVICENAME, name, ref nameSize);
                    string rid_id = (string)Marshal.PtrToStringAnsi(name);

                    // filter Terminal Services and Remote Desktop devices.
                    if (!rid_id.ToUpper().Contains("ROOT"))
                    
                        yield return new Device()
                        
                            Handle = rid.hDevice,
                            ID = rid_id,
                            Type = (Type)rid.dwType,
                            Description = GetRawInputDeviceDescription(rid_id)
                        ;

                        Marshal.FreeHGlobal(name);
                    
                
            

            Marshal.FreeHGlobal(buff);
        
        else
            throw new ApplicationException("An error occurred while retrieving a list of raw input devices");
    

    public static void Register(IntPtr hwnd, REGISTERCLASS[] regs)
    
        Debug.Assert(hwnd != IntPtr.Zero);

        // Usage Pages and Usages:
        // http://www.usb.org/developers/devclass_docs/Hut1_12.pdf

        var rid = new Win32.RAWINPUTDEVICE[regs.Length];
        for (int i = 0; i < regs.Length; ++i)
        
            rid[i].dwFlags = (uint)regs[i].flags;
            rid[i].usUsage = regs[i].usage;
            rid[i].usUsagePage = (ushort)regs[i].usagePage;
            rid[i].hwndTarget = hwnd;
        

        if (Win32.RegisterRawInputDevices(rid, (UIntPtr)rid.Length, (UIntPtr)Marshal.SizeOf(typeof(Win32.RAWINPUTDEVICE))) == IntPtr.Zero)
            throw new ApplicationException("Failed to register raw input devices");
    

    public class Device
    
        public static bool operator ==(Device x, Device y)  if ((object)x != null & (object)y != null)  return x.Handle == y.Handle;  else return (object)x == null && (object)y == null; 
        public static bool operator !=(Device x, Device y)  return !(x == y); 

        public override bool Equals(object obj)  return this == (Device)obj; 
        public override int GetHashCode()  return base.GetHashCode(); 

        public IntPtr Handle  get; set; 
        public Type Type  get; set; 
        public string ID  get; set; 
        public string Description  get; set; 
    

    public struct HIDDATA
    
        public uint size;
        public uint count;
        public byte[] raw;
    

    public struct KEYBOARDDATA
    
        public ushort makeCode;
        public KeyboardFlag flags;
        public ushort vKey;
        public MessageContext message;
        public uint extraInfo;
    

    public struct MOUSEDATA
    
        public MouseFlag flags;
        public MouseTransition transitions;
        public ushort wheelDelta;
        public int motionX;
        public int motionY;
        public uint extraInfo;
    

    public struct REGISTERCLASS
    
        public UsagePage usagePage;
        public ushort usage;
        public ModeFlag flags;
    

    public enum KeyboardFlag : ushort
    
        KeyUp = Win32.RI_KEY_BREAK,
        KeyDown = Win32.RI_KEY_MAKE,
        KeyLeft = Win32.RI_KEY_E0,
        KeyRight = Win32.RI_KEY_E1
    

    public enum MouseFlag : ushort
    
        AttributesChanged = Win32.MOUSE_ATTRIBUTES_CHANGED,
        MoveRelative = Win32.MOUSE_MOVE_RELATIVE,
        MoveAbsolute = Win32.MOUSE_MOVE_ABSOLUTE,
        VirtualDesktop = Win32.MOUSE_VIRTUAL_DESKTOP
    

    public enum MouseTransition : ushort
    
        LeftButtonDown = Win32.RI_MOUSE_LEFT_BUTTON_DOWN,
        LeftButtonUp = Win32.RI_MOUSE_LEFT_BUTTON_UP,
        MiddleButtonDown = Win32.RI_MOUSE_MIDDLE_BUTTON_DOWN,
        MiddleButtonUp = Win32.RI_MOUSE_MIDDLE_BUTTON_UP,
        RightButtonDown = Win32.RI_MOUSE_RIGHT_BUTTON_DOWN,
        RightButtonUp = Win32.RI_MOUSE_RIGHT_BUTTON_UP,
        XButton1Down = Win32.RI_MOUSE_BUTTON_4_DOWN,
        XButton1Up = Win32.RI_MOUSE_BUTTON_4_UP,
        XButton2Down = Win32.RI_MOUSE_BUTTON_5_DOWN,
        XButton2Up = Win32.RI_MOUSE_BUTTON_5_UP,
        MouseWheel = Win32.RI_MOUSE_WHEEL
    

    public enum CommandFlag
    
        Header = Win32.RID_HEADER,
        Input = Win32.RID_INPUT
    

    public enum ModeFlag : uint
    
        Default = 0,
        ApplicationKeys = Win32.RIDEV_APPKEYS,
        CaptureMouse = Win32.RIDEV_CAPTUREMOUSE,
        DeviceNotify = Win32.RIDEV_DEVNOTIFY,
        Exclude = Win32.RIDEV_EXCLUDE,
        ExcludeInputSink = Win32.RIDEV_EXINPUTSINK,
        InputSink = Win32.RIDEV_INPUTSINK,
        NoHotKeys = Win32.RIDEV_NOHOTKEYS,
        NoLegacy = Win32.RIDEV_NOLEGACY,
        PageOnly = Win32.RIDEV_PAGEONLY,
        Remove = Win32.RIDEV_REMOVE
    ;

    public enum UsagePage : ushort
    
        Undefined = 0x00,
        GenericDesktopControls = 0x01,
        SimulationControls = 0x02,
        VRControls = 0x03,
        SportControls = 0x04,
        GameControls = 0x05,
        GenericDeviceControls = 0x06,
        Keyboard = 0x07,
        Keypad = Keyboard,
        LEDs = 0x08,
        Button = 0x09,
        Ordinal = 0x0a,
        Telephony = 0x0b,
        Consumer = 0x0c,
        Digitizer = 0x0d,
        PIDPage = 0x0f,
        Unicode = 0x10,
        AlphanumericDisplay = 0x14,
        MedicalInstruments = 0x40,
        MonitorPage0 = 0x80,
        MonitorPage1 = 0x81,
        MonitorPage2 = 0x82,
        MonitorPage3 = 0x83,
        PowerPage0 = 0x84,
        PowerPage1 = 0x85,
        PowerPage2 = 0x86,
        PowerPage3 = 0x87,
        BarCodeScannerPages = 0x8c,
        Scale = 0x8d,
        MagneticStripeReadingDevices = 0x8e,
        ReservedPointofSalePages = 0x8f,
        CameraControlPage = 0x90,
        ArcadePage = 0x91
    

    /// <see cref="http://www.usb.org/developers/devclass_docs/pos1_02.pdf"/>
    public enum BarCodeScannerPages : ushort
    
        BarCodeScanner = 0x0002
    

    public enum Type : uint
    
        Mouse = Win32.RIM_TYPEMOUSE,
        Keyboard = Win32.RIM_TYPEKEYBOARD,
        HID = Win32.RIM_TYPEHID
    

    private static string GetRawInputDeviceDescription(string deviceid)
    
        string[] id = deviceid.Substring(4).Split('#');

        // get registry entry by appropriate key
        return ((string)Registry.LocalMachine.OpenSubKey(string.Format(
            @"System\CurrentControlSet\Enum\0\1\2",
            id[0], id[1], id[2]), false
        ).GetValue("DeviceDesc")).Split(';')[1];
    

class Win32 导入使用的 Win32 API 函数并包含它们使用的一些常量:

public static class Win32

    // mouse state flags
    public const ushort MOUSE_ATTRIBUTES_CHANGED = 4, // Mouse attributes changed; application needs to query the mouse attributes.
                        MOUSE_MOVE_RELATIVE = 0, // Mouse movement data is relative to the last mouse position.
                        MOUSE_MOVE_ABSOLUTE = 1, // Mouse movement data is based on absolute position.
                        MOUSE_VIRTUAL_DESKTOP = 2; // Mouse coordinates are mapped to the virtual desktop (for a multiple monitor system).

    // mouse transition state flags
    public const ushort RI_MOUSE_LEFT_BUTTON_DOWN = 0x0001, // Left button changed to down.
                        RI_MOUSE_LEFT_BUTTON_UP = 0x0002, // Left button changed to up.
                        RI_MOUSE_MIDDLE_BUTTON_DOWN = 0x0010, // Middle button changed to down.
                        RI_MOUSE_MIDDLE_BUTTON_UP = 0x0020, // Middle button changed to up.
                        RI_MOUSE_RIGHT_BUTTON_DOWN = 0x0004, // Right button changed to down.
                        RI_MOUSE_RIGHT_BUTTON_UP = 0x0008, // Right button changed to up.
                        RI_MOUSE_BUTTON_1_DOWN = 0x0001, // RI_MOUSE_LEFT_BUTTON_DOWN
                        RI_MOUSE_BUTTON_1_UP = 0x0002, // RI_MOUSE_LEFT_BUTTON_UP
                        RI_MOUSE_BUTTON_2_DOWN = 0x0004, // RI_MOUSE_RIGHT_BUTTON_DOWN
                        RI_MOUSE_BUTTON_2_UP = 0x0008, // RI_MOUSE_RIGHT_BUTTON_UP
                        RI_MOUSE_BUTTON_3_DOWN = 0x0010, // RI_MOUSE_MIDDLE_BUTTON_DOWN
                        RI_MOUSE_BUTTON_3_UP = 0x0020, // RI_MOUSE_MIDDLE_BUTTON_UP
                        RI_MOUSE_BUTTON_4_DOWN = 0x0040, // XBUTTON1 changed to down.
                        RI_MOUSE_BUTTON_4_UP = 0x0080, // XBUTTON1 changed to up.
                        RI_MOUSE_BUTTON_5_DOWN = 0x0100, // XBUTTON2 changed to down.
                        RI_MOUSE_BUTTON_5_UP = 0x0200, // XBUTTON2 changed to up.
                        RI_MOUSE_WHEEL = 0x0400; // Raw input comes from a mouse wheel. The wheel delta is stored in usButtonData.

    // keyboard scan code flags
    public const ushort RI_KEY_BREAK = 1,
                        RI_KEY_E0 = 2,
                        RI_KEY_E1 = 4,
                        RI_KEY_MAKE = 0;

    // device types
    public const int RIM_TYPEMOUSE = 0,
                     RIM_TYPEKEYBOARD = 1,
                     RIM_TYPEHID = 2;

    public const int RIDI_PREPARSEDDATA = 0x20000005,
                     RIDI_DEVICENAME = 0x20000007, // the return valus is the character length, not the byte size
                     RIDI_DEVICEINFO = 0x2000000b;

    // mode flags
    public const int RIDEV_REMOVE = 0x00000001,
                     RIDEV_EXCLUDE = 0x00000010,
                     RIDEV_PAGEONLY = 0x00000020,
                     RIDEV_NOLEGACY = 0x00000030,
                     RIDEV_INPUTSINK = 0x00000100,
                     RIDEV_CAPTUREMOUSE = 0x00000200, // effective when mouse nolegacy is specified, otherwise it would be an error
                     RIDEV_NOHOTKEYS = 0x00000200, // effective for keyboard.
                     RIDEV_APPKEYS = 0x00000400, // effective for keyboard.
                     RIDEV_EXINPUTSINK = 0x00001000,
                     RIDEV_DEVNOTIFY = 0x00002000,
                     RIDEV_EXMODEMASK = 0x000000F0;

    // command flag
    public const int RID_HEADER = 0x10000005,
                     RID_INPUT = 0x10000003;    

    /// <summary>
    /// Contains information about a raw input device.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWINPUTDEVICELIST 
    ///     HANDLE hDevice;
    ///     DWORD  dwType;
    ///  RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWINPUTDEVICELIST
    
        public IntPtr hDevice;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwType;
    

    /// <summary>
    /// Defines information for the raw input devices.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWINPUTDEVICE 
    ///     USHORT usUsagePage;
    ///     USHORT usUsage;
    ///     DWORD  dwFlags;
    ///     HWND   hwndTarget;
    ///  RAWINPUTDEVICE, *PRAWINPUTDEVICE, *LPRAWINPUTDEVICE;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWINPUTDEVICE
    
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsagePage;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsage;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwFlags;
        public IntPtr hwndTarget;
    

    /// <summary>
    /// Contains information about the state of the mouse.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWMOUSE 
    ///     USHORT usFlags;
    ///     union 
    ///         ULONG  ulButtons;
    ///         struct 
    ///             USHORT usButtonFlags;
    ///             USHORT usButtonData;
    ///         ;
    ///     ;
    ///     ULONG  ulRawButtons;
    ///     LONG   lLastX;
    ///     LONG   lLastY;
    ///     ULONG  ulExtraInformation;
    ///  RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;
    /// </remarks>
    [StructLayout(LayoutKind.Explicit)]
    public struct RAWMOUSE
    
        [FieldOffset(0), MarshalAs(UnmanagedType.U2)]
        public ushort usFlags;
        [FieldOffset(4), MarshalAs(UnmanagedType.U4)]
        public uint ulButtons;
        [FieldOffset(4), MarshalAs(UnmanagedType.U2)]
        public ushort usButtonFlags;
        [FieldOffset(6), MarshalAs(UnmanagedType.U2)]
        public ushort usButtonData;
        [FieldOffset(8), MarshalAs(UnmanagedType.U4)]
        public uint ulRawButtons;
        [FieldOffset(12), MarshalAs(UnmanagedType.I4)]
        public int lLastX;
        [FieldOffset(16), MarshalAs(UnmanagedType.I4)]
        public int lLastY;
        [FieldOffset(20), MarshalAs(UnmanagedType.U4)]
        public uint ulExtraInformation;
    

    /// <summary>
    /// Contains information about the state of the keyboard.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWKEYBOARD 
    ///     USHORT MakeCode;
    ///     USHORT Flags;
    ///     USHORT Reserved;
    ///     USHORT VKey;
    ///     UINT   Message;
    ///     ULONG  ExtraInformation;
    ///  RAWKEYBOARD, *PRAWKEYBOARD, *LPRAWKEYBOARD;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWKEYBOARD
    
        [MarshalAs(UnmanagedType.U2)]
        public ushort MakeCode;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Flags;
        [MarshalAs(UnmanagedType.U2)]
        public ushort Reserved;
        [MarshalAs(UnmanagedType.U2)]
        public ushort VKey;
        [MarshalAs(UnmanagedType.SysUInt)]
        public UIntPtr Message;
        [MarshalAs(UnmanagedType.U4)]
        public uint ExtraInformation;
    

    /// <summary>
    /// Describes the format of the raw input from a Human Interface Device (HID).
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWHID 
    ///     DWORD dwSizeHid;
    ///     DWORD dwCount;
    ///     BYTE  bRawData[1];
    ///  RAWHID, *PRAWHID, *LPRAWHID;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWHID
    
        [MarshalAs(UnmanagedType.U4)]
        public uint dwSizeHid;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwCount;
    

    /// <summary>
    /// Contains the header information that is part of the raw input data.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWINPUTHEADER 
    ///     DWORD  dwType;
    ///     DWORD  dwSize;
    ///     HANDLE hDevice;
    ///     WPARAM wParam;
    ///  RAWINPUTHEADER, *PRAWINPUTHEADER;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWINPUTHEADER
    
        [MarshalAs(UnmanagedType.U4)]
        public uint dwType;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwSize;
        public IntPtr hDevice;
        [MarshalAs(UnmanagedType.SysUInt)]
        public UIntPtr wParam;
    

    /// <summary>
    /// Contains the raw input from a device.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRAWINPUT 
    ///     RAWINPUTHEADER header;
    ///     union 
    ///         RAWMOUSE    mouse;
    ///         RAWKEYBOARD keyboard;
    ///         RAWHID      hid;
    ///      data;
    ///  RAWINPUT, *PRAWINPUT, *LPRAWINPUT;
    /// </remarks>
    [StructLayout(LayoutKind.Explicit)]
    public struct RAWINPUT
    
        [FieldOffset(0)]
        public RAWINPUTHEADER header;
#if IA32
        [FieldOffset(16)]
        public RAWMOUSE mouse;
        [FieldOffset(16)]
        public RAWKEYBOARD keyboard;
        [FieldOffset(16)]
        public RAWHID hid;
#elif INTEL64
        [FieldOffset(24)]
        public RAWMOUSE mouse;
        [FieldOffset(24)]
        public RAWKEYBOARD keyboard;
        [FieldOffset(24)]
        public RAWHID hid;
#endif
    

    /// <summary>
    /// Defines the raw input data coming from the specified keyboard.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRID_DEVICE_INFO_KEYBOARD 
    ///     DWORD dwType;
    ///     DWORD dwSubType;
    ///     DWORD dwKeyboardMode;
    ///     DWORD dwNumberOfFunctionKeys;
    ///     DWORD dwNumberOfIndicators;
    ///     DWORD dwNumberOfKeysTotal;
    ///  RID_DEVICE_INFO_KEYBOARD, *PRID_DEVICE_INFO_KEYBOARD;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RID_DEVICE_INFO_KEYBOARD
    
        [MarshalAs(UnmanagedType.U4)]
        public uint dwType;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwSubType;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwKeyboardMode;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwNumberOfFunctionKeys;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwNumberOfIndicators;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwNumberOfKeysTotal;
    

    /// <summary>
    /// Defines the raw input data coming from the specified mouse.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRID_DEVICE_INFO_MOUSE 
    ///     DWORD dwId;
    ///     DWORD dwNumberOfButtons;
    ///     DWORD dwSampleRate;
    ///     BOOL  fHasHorizontalWheel;
    ///  RID_DEVICE_INFO_MOUSE, *PRID_DEVICE_INFO_MOUSE;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RID_DEVICE_INFO_MOUSE
    
        [MarshalAs(UnmanagedType.U4)]
        public uint dwId;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwNumberOfButtons;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwSampleRate;
        [MarshalAs(UnmanagedType.SysInt)]
        public IntPtr fHasHorizontalWheel;
    

    /// <summary>
    /// Defines the raw input data coming from the specified Human Interface Device (HID).
    /// </summary>
    /// <remarks>
    /// typedef struct tagRID_DEVICE_INFO_HID 
    ///     DWORD  dwVendorId;
    ///     DWORD  dwProductId;
    ///     DWORD  dwVersionNumber;
    ///     USHORT usUsagePage;
    ///     USHORT usUsage;
    ///  RID_DEVICE_INFO_HID, *PRID_DEVICE_INFO_HID;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct RID_DEVICE_INFO_HID
    
        [MarshalAs(UnmanagedType.U4)]
        public uint dwVendorId;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwProductId;
        [MarshalAs(UnmanagedType.U4)]
        public uint dwVersionNumber;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsagePage;
        [MarshalAs(UnmanagedType.U2)]
        public ushort usUsage;
    

    /// <summary>
    /// Defines the raw input data coming from any device.
    /// </summary>
    /// <remarks>
    /// typedef struct tagRID_DEVICE_INFO 
    ///     DWORD cbSize;
    ///     DWORD dwType;
    ///     union 
    ///         RID_DEVICE_INFO_MOUSE    mouse;
    ///         RID_DEVICE_INFO_KEYBOARD keyboard;
    ///         RID_DEVICE_INFO_HID      hid;
    ///      ;
    ///  RID_DEVICE_INFO, *PRID_DEVICE_INFO, *LPRID_DEVICE_INFO;
    /// </remarks>
    [StructLayout(LayoutKind.Explicit)]
    public struct RID_DEVICE_INFO
    
        [FieldOffset(0), MarshalAs(UnmanagedType.U4)]
        public uint cbSize;
        [FieldOffset(4), MarshalAs(UnmanagedType.U4)]
        public uint dwType;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_MOUSE mouse;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_KEYBOARD keyboard;
        [FieldOffset(8)]
        public RID_DEVICE_INFO_HID hid;
    

    /// <summary>
    /// The POINT structure defines the x- and y- coordinates of a point.
    /// </summary>
    /// <remarks>
    /// typedef struct tagPOINT 
    ///     LONG x;
    ///     LONG y;
    ///  POINT, *PPOINT;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    
        [MarshalAs(UnmanagedType.U4)]
        public long x;
        [MarshalAs(UnmanagedType.U4)]
        public long y;
     

    /// <summary>
    /// Contains message information from a thread's message queue.
    /// </summary>
    /// <remarks>
    /// typedef struct tagMSG 
    ///     HWND   hwnd;
    ///     UINT   message;
    ///     WPARAM wParam;
    ///     LPARAM lParam;
    ///     DWORD  time;
    ///     POINT  pt;
    ///  MSG, *PMSG, *LPMSG;
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct MSG
    
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.SysUInt)]
        public MessageContext message;
        public IntPtr wParam;
        public IntPtr lParam;
        [MarshalAs(UnmanagedType.U4)]
        public ulong time;
        public POINT pt;
    

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);     
    // ...
    // Import other API functions used above
    // ...

【讨论】:

你能否给一个 WPF 中的示例项目的 url,看看你是怎么做到的? Win32 来自哪里? @qakmak 我已经编辑了答案并提供了Win32 的部分实现。请注意,我省略了DllImports,因为我的回答太长了。【参考方案3】:

您在使用 .Net 的 POS 和 USB HID 设备方面走在了正确的轨道上。 Scanner 将提供一个数据事件供您处理。您遇到的问题以及我遇到的同样问题是,在 WPF 中,您无法从 POSExplorer 对象本机接收数据事件。这是因为 POSExplorer 需要 Windows 窗体的句柄。事实证明,来自对象的 WPF 是不可接受的,因为该技术中使用了线程模型。

如果 Microsoft 可以为 WPF 创建一个 POSExplorer,那么您将被设置,但在此之前,最简单的解决方案是使用 Windows 窗体创建一个单独的项目,以便您可以处理来自 POSExplorer 的数据事件。之后,您可以处理将该信息传达给您的 WPF UI 的小问题。

【讨论】:

请注意我新创建的帖子。【参考方案4】:

我尝试通过使用 WinAPI 使其工作。我可以枚举键盘、鼠标和其他人机接口设备:

int main()

    UINT num_devs;
    GetRawInputDeviceList(NULL, &num_devs, sizeof(RAWINPUTDEVICELIST));
    RAWINPUTDEVICELIST* dev_list = new RAWINPUTDEVICELIST[num_devs];
    UINT stored_devs = GetRawInputDeviceList(dev_list, &num_devs, sizeof(RAWINPUTDEVICELIST));

    for( int i = 0; i < stored_devs; ++i )
    
        UINT            size;
        RID_DEVICE_INFO dev_info;
        char            dev_name[256] = 0;

        size = sizeof(dev_name);
        GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, dev_name, &size);
        size = sizeof(RID_DEVICE_INFO);
        GetRawInputDeviceInfo(dev_list[i].hDevice, RIDI_DEVICEINFO, &dev_info, &size);

        std::cout << "Device Name: " << dev_name << "Device Type: ";
        switch( dev_info.dwType )
        
        case RIM_TYPEHID:
            std::cout << "HID";
            break;
        case RIM_TYPEKEYBOARD:
            std::cout << "Keyboard";
            break;
        case RIM_TYPEMOUSE:
            std::cout << "Mouse";
        
        std::cout << std::endl;
    

    delete dev_list;
    return 0;

但似乎 GetRawInputDeviceList 也提供 RDP 设备和其他虚拟设备。如何识别我的键盘和扫描仪?

【讨论】:

以上是关于.NET 的 POS |区分(条形码)扫描仪和键盘输入的主要内容,如果未能解决你的问题,请参考以下文章

如何检测键盘楔形扫描仪条形码输入到网络输入并阻止键盘输入

检测键盘/条形码扫描仪事件的来源

VB.NET如何操作条码扫描枪,如何设置,如何进行条形码的设置及打印

C# winform 怎么让窗体接受条码扫描器的输入

使用jquery检测扫描仪输入

Android:如何将通过USB连接的外部条形码扫描仪设备集成到Android应用程序[关闭]