最近有个项目客户有个要求有个界面只准扫码枪输入,不准用键盘输入,我研究了一下,找了找网上的代码,实现了一下,主要原理是提前知道输入信息的来源,判断哪个设备的,然后如果是键盘的,不往后面传递信息好了。
具体代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testScanCode
{
[StructLayout(LayoutKind.Sequential)]
internal struct RAWINPUTDEVICE
{
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
[MarshalAs(UnmanagedType.U4)]
public int dwFlags;
public IntPtr hwndTarget;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RAWINPUTHEADER
{
[MarshalAs(UnmanagedType.U4)]
public int dwType;
[MarshalAs(UnmanagedType.U4)]
public int dwSize;
public IntPtr hDevice;
[MarshalAs(UnmanagedType.U4)]
public int wParam;
}
[StructLayout(LayoutKind.Explicit)]
internal struct RAWINPUT
{
[FieldOffset(0)]
public RAWINPUTHEADER header;
[FieldOffset(16)]
public RAWMOUSE mouse;
[FieldOffset(16)]
public RAWKEYBOARD keyboard;
[FieldOffset(16)]
public RAWHID hid;
}
[StructLayout(LayoutKind.Sequential)]
internal 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.U4)]
public uint Message;
[MarshalAs(UnmanagedType.U4)]
public uint ExtraInformation;
}
[StructLayout(LayoutKind.Explicit)]
internal struct RAWMOUSE
{
[MarshalAs(UnmanagedType.U2)]
[FieldOffset(0)]
public ushort usFlags;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(4)]
public uint ulButtons;
[FieldOffset(4)]
public BUTTONSSTR buttonsStr;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(8)]
public uint ulRawButtons;
[FieldOffset(12)]
public int lLastX;
[FieldOffset(16)]
public int lLastY;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(20)]
public uint ulExtraInformation;
}
[StructLayout(LayoutKind.Sequential)]
internal struct BUTTONSSTR
{
[MarshalAs(UnmanagedType.U2)]
public ushort usButtonFlags;
[MarshalAs(UnmanagedType.U2)]
public ushort usButtonData;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RAWHID
{
[MarshalAs(UnmanagedType.U4)]
public int dwSizHid;
[MarshalAs(UnmanagedType.U4)]
public int dwCount;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_HID
{
[MarshalAs(UnmanagedType.U4)]
public int dwVendorId;
[MarshalAs(UnmanagedType.U4)]
public int dwProductId;
[MarshalAs(UnmanagedType.U4)]
public int dwVersionNumber;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_KEYBOARD
{
[MarshalAs(UnmanagedType.U4)]
public int dwType;
[MarshalAs(UnmanagedType.U4)]
public int dwSubType;
[MarshalAs(UnmanagedType.U4)]
public int dwKeyboardMode;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfFunctionKeys;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfIndicators;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfKeysTotal;
}
[StructLayout(LayoutKind.Explicit)]
internal struct RID_DEVICE_INFO
{
[FieldOffset(0)]
public int cbSize;
[FieldOffset(4)]
public int 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;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_MOUSE
{
[MarshalAs(UnmanagedType.U4)]
public int dwId;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfButtons;
[MarshalAs(UnmanagedType.U4)]
public int dwSampleRate;
[MarshalAs(UnmanagedType.U4)]
public int fHasHorizontalWheel;
}
public partial class Form1 : Form
{
[DllImport("User32.dll")]
extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
[DllImport("User32.dll")]
extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);
[DllImport("User32.dll")]
extern static uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
private const int RIDEV_INPUTSINK = 0x100;
private const int RIDEV_NoLegacy = 0x30;
private const int WM_INPUT = 0x00FF;
private const uint RID_INPUT = 0x10000003;
private const uint RIDI_DEVICENAME = 0x20000007;
bool isKeyBoard1 = true;
string keyBoard = "VID_24AE";
public Form1()
{
InitializeComponent();
RegWM_INPUT();
}
private void RegWM_INPUT()
{
RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];
rid[0].usUsagePage = 0x01;
rid[0].usUsage = 0x06;
//rid[0].dwFlags = RIDEV_INPUTSINK| RIDEV_NoLegacy;//当前设置:焦点非当前窗口时依旧接收到WM_INPUT消息,可根据此特性实现当使用条码枪时激活本窗口
rid[0].hwndTarget = this.Handle;
RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0]));
}
protected override void WndProc(ref Message message)
{
if (message.Msg == WM_INPUT)
processMessage(message);
//string aa = message.Msg.ToString();
base.WndProc(ref message);
}
private void processMessage(Message message)
{
uint dwSize = 0;
GetRawInputData(message.LParam, RID_INPUT, IntPtr.Zero, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)));
IntPtr buffer = Marshal.AllocHGlobal((int)dwSize);
GetRawInputData(message.LParam, RID_INPUT, buffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)));
RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT));
uint size = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICENAME, IntPtr.Zero, ref size);
IntPtr pData = Marshal.AllocHGlobal((int)size);
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICENAME, pData, ref size);
string deviceName = (string)Marshal.PtrToStringAnsi(pData);
//MessageBox.Show(deviceName);
//判断deviceName来自哪个设备。做对应的处理
//doSomething..
//
if (deviceName.Contains(keyBoard))
{
isKeyBoard1 = false;
}
else
{
isKeyBoard1 = true;
}
//下面两句是释放了缓存
Marshal.FreeHGlobal(buffer);
Marshal.FreeHGlobal(pData);
}
protected override bool ProcessKeyPreview(ref Message m)//重写此函数可拦截扫码枪字符输入
{
if (isKeyBoard1)//如果为条码枪输入则不对窗口内的控件进行录入
{
return true;
}
return base.ProcessKeyPreview(ref m);
}
protected override bool ProcessDialogKey(Keys keyData)//重写此函数可拦截扫码枪回车触发按钮
{
if (isKeyBoard1)
{
return true;
}
return base.ProcessDialogKey(keyData);
}
}
}
参考文章:
C# 多输入设备识别 扫码枪键盘区分RAWINPUT原始输入简易开发笔记_c#rawinput_qq_281781648的博客-CSDN博客