由于扫码枪的输出方式与键盘输出是一样的,由此可以使用键盘钩子来捕获扫码枪数据
using System;
using System.Timers;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
//安装钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
//卸下钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//下一个钩挂的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
[DllImport("user32")]
public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
[DllImport("user32")]
public static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
public static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_SYSKEYDOWN = 0x104;
public const int WM_SYSKEYUP = 0x105;
public const int WH_KEYBOARD_LL = 13;
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
private int HookIntPtr;
private HookProc KeysHookDelegate;
///
/// 为了延迟释放已经捕获到了的键值
///
private static readonly System.Timers.Timer ReleaseTimer = new System.Timers.Timer();
///
/// 安装钩子
///
public void KeysHook_Set()
{
KeysHookDelegate = new HookProc(KeyboardHookProc);
Process NewPro = Process.GetCurrentProcess();
ProcessModule NewProMod = NewPro.MainModule;
IntPtr NewIntPtr = GetModuleHandle(NewProMod.ModuleName);
HookIntPtr = SetWindowsHookEx(WH_KEYBOARD_LL, KeysHookDelegate, NewIntPtr, 0);
ReleaseTimer.Stop();
ReleaseTimer.Interval = LoadSetup.Default.KeysDelay;
ReleaseTimer.Elapsed += new ElapsedEventHandler(ReleaseTimer_Tick);
}
///
/// 卸载钩子
///
public void KeysHook_Unload()
{
try
{
UnhookWindowsHookEx(HookIntPtr);
ReleaseTimer.Stop();
}
catch { }
}
///
/// 释放键列表
///
private readonly List KeysList_Release = new List();
///
/// 释放所有按键
///
private void ReleaseAllKeys()
{
CodeStr = "";
try
{
foreach (Keys key in KeysList_Release)
{
KeysReleaseing = true;
keybd_event(key, 0, 0, 0);
keybd_event(key, 0, 2, 0);
KeysUp = true;
}
}
catch { }
KeysUp = true;
KeysReleaseing = false;
KeysList_Release.Clear();
ReleaseTimer.Stop();
}
private int OverTime = 0;
///
/// 延时释放已捕获的键值,一般是释放手输的键
///
private void ReleaseTimer_Tick(object sender, ElapsedEventArgs e)
{
if (OverTime >= 1)
{
ReleaseAllKeys();
OverTime = 0;
}
OverTime++;
}
///
/// 捕获到的字符串
///
private string CodeStr = "";
///
/// 来判断是否是手输的
///
private DateTime DownTime = DateTime.Now;
private DateTime UpTime = DateTime.Now;
private TimeSpan NewSpan = new TimeSpan();
///
/// 来判断是否释放不需要的数据
///
private bool KeysReleaseing = false;
///
/// 来判断键盘按下后是否放开
///
private bool KeysUp = true;
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode >= 0)
{
KeyboardHookStruct KeyDataFromHook = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
Keys AimKeys = (Keys)KeyDataFromHook.vkCode;
#region Enter处理 一般扫码枪输出完后都会再输出个Enter键
if (AimKeys == Keys.Enter)
{
///判断捕获到的是否是自己所需要的数据
bool IsPayCode = DataHelper.PayCode_Judge(CodeStr, out bool Vip) ;
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
if (IsPayCode)
{
KeysList_Release.Clear();
string TemCode = CodeStr;
CodeStr = "";
//“TemCode”就是所需要的值了,就可以直接去执行相关函数
return 1;
}
else
{
ReleaseAllKeys();
}
}
else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
{
if (IsPayCode)
{
return 1;
}
}
}
#endregion
#region 数字处理 这个可以自行选择需要捕获的键盘值
else if ((KeyDataFromHook.vkCode >= (int)Keys.D0 && KeyDataFromHook.vkCode <= (int)Keys.D9))
{
//判断是否是释放键值中
if (!KeysReleaseing)
{
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
//这是把键值转换为字符串
CodeStr += KeysHelper.ToStr(AimKeys);
KeysList_Release.Add(AimKeys);
DownTime = DateTime.Now;
OverTime = 0;
if (KeysUp)
{
ReleaseTimer.Start();
KeysUp = false;
}
else
{
ReleaseAllKeys();
}
}
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
{
KeysUp = true;
UpTime = DateTime.Now;
NewSpan = UpTime.Subtract(DownTime);
//来判断是否是手输,一般扫码枪在20ms以下,这个值可以自己设
if (NewSpan.Milliseconds > LoadSetup.Default.KeysDelay)
{
CodeStr = "";
}
}
//return 1是键盘不响应
return 1;
}
}
else
{
ReleaseAllKeys();
}
#endregion
}
return CallNextHookEx(HookIntPtr, nCode, wParam, lParam);
}