.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 或 WEPOS(WEB 内容不再可用)的扫描程序具有包装设备驱动程序的 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
的部分实现。请注意,我省略了DllImport
s,因为我的回答太长了。【参考方案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 |区分(条形码)扫描仪和键盘输入的主要内容,如果未能解决你的问题,请参考以下文章