用以下winapi可获取设备原始输入信息,即包含硬件标识的信息:
[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);
重写窗体的消息处理函数,当接收到WM_INPUT消息时,则进行该消息所对应的原始输入信息的获取,然后即可得到硬件标识(在不知道条码枪的硬件标识的情况下,可将GetScannerName变量设置为true,然后将首个进行键盘消息录入的硬件标识为条码枪)之后即可将条码枪录入标识变量IsScannerInput设置为true:
public FrmMain()
{
InitializeComponent();
RegWM_INPUT();
}
/// <summary>
/// 订阅WM_INPUT消息
/// </summary>
private void RegWM_INPUT()
{
RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];
rid[0].usUsagePage = 0x01;
rid[0].usUsage = 0x06;
rid[0].dwFlags = RIDEV_INPUTSINK;//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 m)
{
if (m.Msg == WM_INPUT)
{
processMessage(m);
}
base.WndProc(ref m);
}
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);
if (GetScannerName)
{
ScannerName = txtTiaoMaQiang.Text = deviceName;
GetScannerName = false;
}
if (deviceName == ScannerName)
{
IsScannerInput = true;
this.Activate();
if (raw.keyboard.Flags == 1)
{
switch (raw.keyboard.VKey)//目前是仅转译了数字,如需字母与符号可在此扩展
{
case 0x30:
ScannerCodeCache.Append('0');
break;
case 0x31:
ScannerCodeCache.Append('1');
break;
case 0x32:
ScannerCodeCache.Append('2');
break;
case 0x33:
ScannerCodeCache.Append('3');
break;
case 0x34:
ScannerCodeCache.Append('4');
break;
case 0x35:
ScannerCodeCache.Append('5');
break;
case 0x36:
ScannerCodeCache.Append('6');
break;
case 0x37:
ScannerCodeCache.Append('7');
break;
case 0x38:
ScannerCodeCache.Append('8');
break;
case 0x39:
ScannerCodeCache.Append('9');
break;
case 0x3a:
ScannerCodeCache.Append('0');
break;
case 0x0d:
{
string _scannerCode = ScannerCodeCache.ToString();
ScannerCodeCache.Clear();
MessageDxUtil.ShowTips(_scannerCode);
break;
}
}
}
}
else
{
IsScannerInput = false;
}
//下面两句是释放了缓存
Marshal.FreeHGlobal(buffer);
Marshal.FreeHGlobal(pData);
}
重写窗口的ProcessKeyPreview函数:
protected override bool ProcessKeyPreview(ref Message m)//重写此函数可拦截扫码枪字符输入
{
if (IsScannerInput)//如果为条码枪输入则不对窗口内的控件进行录入
{
return true;
}
return base.ProcessKeyPreview(ref m);
}
protected override bool ProcessDialogKey(Keys keyData)//重写此函数可拦截扫码枪回车触发按钮
{
if (IsScannerInput)
{
return true;
}
return base.ProcessDialogKey(keyData);
}