public class ScanHook { #region 引用扩展API方法 // 安装钩子 [DllImport("user32.dll")] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); // 卸载钩子 [DllImport("user32.dll")] public static extern bool UnhookWindowsHookEx(int idHook); // 继续下一个钩子 [DllImport("user32.dll")] public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam); // 取得当前线程编号(线程钩子需要用到) [DllImport("kernel32.dll")] static extern int GetCurrentThreadId(); //使用WINDOWS API函数代替获取当前实例的函数,防止钩子失效 [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string name); [DllImport("user32.dll")] private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize); [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("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] protected static extern short GetKeyState(int vKey); #endregion //声明定义 public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); private HookProc KeyboardHookProcedure; public delegate void GetBarcodeHandler(string Barcode); public event GetBarcodeHandler GetBarcodeEvent; public delegate void GetKeyHandler(Keys keys); public event GetKeyHandler GetKeyEvent; private int hKeyboardHook = 0; private List<char> _barcode = new List<char>(); public Keys Prefix { get; set; } public Keys Subffix { get; set; } private string Barcode = string.Empty; private bool IsReading = false; private DateTime? dtScan = null; public int ID { get; set; } 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; protected const byte VK_LSHIFT = 0xA0; protected const byte VK_RSHIFT = 0xA1; [StructLayout(LayoutKind.Sequential)] public struct KeyboardMSG { public int vkCode; public int scanCode; public int flags; public int time; public int dwExtraInfo; public int VK_CONTROL; public int VK_MENU; public int VK_DELETE; } private List<Keys> preKeysList = new List<Keys>();//存放被按下的控制键,用来生成具体的键 // 安装钩子 public void HookStart() { if (hKeyboardHook == 0) { // 创建HookProc实例 //KeyboardHookProcedure = new HookProc(KeyboardHookProc); //KeyboardHookProcedure = new HookProc(KeyboardHookProc2); KeyboardHookProcedure = new HookProc(KeyboardHookProc3); //定义全局钩子 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0); if (hKeyboardHook == 0) { HookStop(); throw new Exception("SetWindowsHookEx failed."); } //Random ran = new Random(); //ID = ran.Next(); //LogWrite.WriteRunLog("ScanHook", "启动钩子" + ID); } } /// <summary> /// 钩子子程就是钩子所要做的事情。 /// </summary> /// <param name="nCode">消息的类型,分HC_ACTION和HC_NOREMOVE</param> /// <param name="wParam">按键的状态(按下或弹起)WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP </param> /// <param name="lParam">按键的相关参数信息</param> /// <returns></returns> private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { //这里可以添加别的功能的代码 //return 1; if (nCode == 0) { KeyboardMSG m = (KeyboardMSG)Marshal.PtrToStructure(lParam, typeof(KeyboardMSG)); if (wParam == 0x100) //WM_KEYDOWN = 0x100 { //DateTime dtNow = DateTime.Now; //double ScanTime = 0; //if (dtScan != null) // ScanTime = (dtNow - dtScan).Value.TotalMilliseconds; //LogWrite.WriteRunLog("ScanHook", m.vkCode.ToString() + "\t" + Convert.ToChar(m.vkCode).ToString() + "\t" + IsReading.ToString()); if (m.vkCode == (int)Prefix && !IsReading) { //LogWrite.WriteRunLog("ScanHook", "开始"); //dtScan = DateTime.Now; _barcode.Clear(); IsReading = true; return 1; } else if (m.vkCode == (int)Subffix && IsReading) { //LogWrite.WriteRunLog("ScanHook", "结束"); Barcode = new String(_barcode.ToArray()); //LogWrite.WriteRunLog("ScanHook", Barcode); IsReading = false; if (GetBarcodeEvent != null) GetBarcodeEvent(Barcode.Trim()); return 1; } else { if (IsReading && m.vkCode >= 21 && m.vkCode <= 126) { if (Control.ModifierKeys == Keys.Shift) { switch (m.vkCode) { case 51: _barcode.Add('#'); break; default: _barcode.Add(Convert.ToChar(m.vkCode)); break; } } else _barcode.Add(Convert.ToChar(m.vkCode)); return 1; } } } } return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } private int KeyboardHookProc2(int nCode, int wParam, IntPtr lParam) { if (nCode >= 0) { if (wParam == 0x100 || wParam == 0x104) { KeyboardMSG m = (KeyboardMSG)Marshal.PtrToStructure(lParam, typeof(KeyboardMSG)); if (m.vkCode == (int)Prefix && !IsReading) { _barcode.Clear(); IsReading = true; return 1; } else if (m.vkCode == (int)Subffix && IsReading) { Barcode = new String(_barcode.ToArray()); IsReading = false; if (GetBarcodeEvent != null) GetBarcodeEvent(Barcode.Trim()); return 1; } else if (IsReading) { if ((m.vkCode >= 8 && m.vkCode <= 47) || (m.vkCode >= 112 && m.vkCode <= 123)) { } else { StringBuilder strKeyName = new StringBuilder(225); if (GetKeyNameText(m.scanCode * 65536, strKeyName, 255) > 0) { string str = strKeyName.ToString().Trim(new char[] { ' ', '\0' }); _barcode.AddRange(str.ToArray()); } } } } } return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } private int KeyboardHookProc3(int nCode, Int32 wParam, IntPtr lParam) { //如果该消息被丢弃(nCode<0)或者没有事件绑定处理程序则不会触发事件 if ((nCode >= 0)) { KeyboardMSG KeyDataFromHook = (KeyboardMSG)Marshal.PtrToStructure(lParam, typeof(KeyboardMSG)); Keys keyData = (Keys)KeyDataFromHook.vkCode; if (GetKeyEvent != null) GetKeyEvent(keyData); if (wParam == WM_KEYDOWN && keyData == Prefix && !IsReading) { _barcode.Clear(); IsReading = true; if (preKeysList != null) preKeysList.Clear(); return 1; } else if (wParam == WM_KEYDOWN && keyData == Subffix && IsReading) { Barcode = new String(_barcode.ToArray()).ToUpper(); IsReading = false; if (preKeysList != null) preKeysList.Clear(); if (GetBarcodeEvent != null) GetBarcodeEvent(Barcode.Trim()); return 1; } if (IsReading) { //if (System.Diagnostics.Debugger.IsAttached && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) // LogWrite.WriteRunLog("ScanHook", keyData.ToString() + "\t" + ((char)KeyDataFromHook.vkCode).ToString() + "\t" + KeyDataFromHook.vkCode + "\t" + KeyDataFromHook.scanCode); //按下控制键 if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1) { preKeysList.Add(keyData); //return 1; } } //WM_KEYDOWN和WM_SYSKEYDOWN消息,将会引发OnKeyDownEvent事件 //if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) //{ // KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); // OnKeyDownEvent(this, e); //} //WM_KEYDOWN消息将引发OnKeyPressEvent if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && IsReading) { byte[] keyState = new byte[256]; GetKeyboardState(keyState); byte[] inBuffer = new byte[2]; if (ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1) { char chr = (char)inBuffer[0]; //chr = (char)KeyDataFromHook.vkCode; if (IsShift()) chr = GetValueByShift(chr); _barcode.Add(chr); } //if ((KeyDataFromHook.vkCode >= 8 && KeyDataFromHook.vkCode <= 47) || (KeyDataFromHook.vkCode >= 112 && KeyDataFromHook.vkCode <= 123)) //{ } //else //{ // if (IsShift()) // _barcode.Add(GetValueByShift(Convert.ToChar(KeyDataFromHook.vkCode))); // else // _barcode.Add(Convert.ToChar(KeyDataFromHook.vkCode)); //} } //松开控制键 if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) if (IsCtrlAltShiftKeys(keyData)) for (int i = preKeysList.Count - 1; i >= 0; i--) if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); } return 1;//不触发其他事件 } } return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } //根据已经按下的控制键生成key private Keys GetDownKeys(Keys key) { Keys rtnKey = Keys.None; foreach (Keys i in preKeysList) { if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; } if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; } if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; } } return rtnKey | key; } private Boolean IsCtrlAltShiftKeys(Keys key) { if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) { return true; } return false; } private char GetValueByShift(char chr) { char ret = chr; switch(chr) { case '`': ret = '~'; break; case '1': ret = '!'; break; case '2': ret = '@'; break; case '3': ret = '#'; break; case '4': ret = '$'; break; case '5': ret = '%'; break; case '6': ret = '^'; break; case '7': ret = '&'; break; case '8': ret = '*'; break; case '9': ret = '('; break; case '0': ret = ')'; break; case '-': ret = '_'; break; case '=': ret = '+'; break; case '[': ret = '{'; break; case ']': ret = '}'; break; case '\\': ret = '|'; break; case ';': ret = ':'; break; case '\'': ret = '"'; break; case ',': ret = '<'; break; case '.': ret = '>'; break; case '/': ret = '?'; break; } return ret; } private bool IsShift() { if (preKeysList == null || preKeysList.Count < 1) return false; return preKeysList.IndexOf(Keys.LShiftKey) > -1 || preKeysList.IndexOf(Keys.RShiftKey) > -1; } // 卸载钩子 public void HookStop() { bool retKeyboard = true; if (hKeyboardHook != 0) { retKeyboard = UnhookWindowsHookEx(hKeyboardHook); hKeyboardHook = 0; //LogWrite.WriteRunLog("ScanHook", "关闭钩子" + ID); } if (!(retKeyboard)) throw new Exception("UnhookWindowsHookEx failed."); } }
扫码枪声明定义:
private LoginResultDto _LoginResult; private ScanHook _ScanHook; private Thread _thdScanHook; public class LoginResultDto{ public long? UserId { get; set; } public string UserName { get; set; } ... ... ... } public class LoginCardNumInput { public string CardNum { get; set; } public string PassWord { get; set; } }
扫码:
#region 扫描钩子 #region 结构体 [DllImport("user32", EntryPoint = "GetMessage")] public static extern int GetMessage( out tagMSG lpMsg, IntPtr hwnd, int wMsgFilterMin, int wMsgFilterMax ); [DllImport("user32", EntryPoint = "DispatchMessage")] public static extern int DispatchMessage( ref tagMSG lpMsg ); [DllImport("user32", EntryPoint = "TranslateMessage")] public static extern int TranslateMessage( ref tagMSG lpMsg ); [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } public struct tagMSG { public int hwnd; public uint message; public int wParam; public long lParam; public uint time; public int pt; } #endregion private void InitScanHook() { _thdScanHook = new Thread(InitScanHookThread); _thdScanHook.IsBackground = true; _thdScanHook.Start(); } private void InitScanHookThread() { _ScanHook = new ScanHook(); _ScanHook.Prefix = AppInfo.KeyPrefix; _ScanHook.Subffix = AppInfo.KeySubffix; _ScanHook.GetBarcodeEvent += ScanHook_GetBarCodeEvent; _ScanHook.HookStart(); CheckForIllegalCrossThreadCalls = false; tagMSG Msgs; while (GetMessage(out Msgs, IntPtr.Zero, 0, 0) > 0) { TranslateMessage(ref Msgs); DispatchMessage(ref Msgs); } } private void ScanHook_GetBarCodeEvent(string loginId) { try { if (String.IsNullOrEmpty(loginId)) return; LoginByLoginId(loginId).Wait(); } catch (Exception ex) { ShowErrorMessage(ex.Message); } } #endregion
==================================================================================================================================================================================
public class CardReader { public CardReader(string Port, int BaudRate) { port = Port; baudrate = BaudRate; } private static int comHandler = int.MinValue; public bool IsConn { get { return comHandler != int.MinValue; } } public string port; public int baudrate; public void Conn() { byte[] com = new byte[10]; UTF8Encoding u = new UTF8Encoding(); com = u.GetBytes(port); comHandler = CardApi.API_OpenComm(com, baudrate); if (comHandler == 0) throw new Exception("打开端口失败!"); } public void Close() { if (IsConn) { CardApi.API_CloseComm(comHandler); comHandler = int.MinValue; } } public string ReadCardNo() { if (!IsConn) return null; byte mode1 = (byte)0x00;// (readKeyB.Checked) ? (byte)0x01 : (byte)0x00; byte mode2 = (byte)0x00;// (readAll.Checked) ? (byte)0x01 : (byte)0x00; byte mode = (byte)((mode1 << 1) | mode2); byte blk_add = Convert.ToByte("10", 16); byte num_blk = Convert.ToByte("01", 16); string ReadKey = "FF FF FF FF FF FF"; byte[] snr = new byte[6]; snr = convertSNR(ReadKey, 6); if (snr == null) throw new Exception("序列号无效!"); byte[] buffer = new byte[16 * num_blk]; int nRet = CardApi.API_PCDRead(comHandler, 0, mode, blk_add, num_blk, snr, buffer); if (nRet != 0) throw new Exception(GetStatue(buffer[0])); return GetHexData(snr, 0, 4); } //转换卡号专用 private byte[] convertSNR(string str, int keyN) { string regex = "[^a-fA-F0-9]"; string tmpJudge = Regex.Replace(str, regex, ""); //长度不对,直接退回错误 if (tmpJudge.Length != 12) return null; string[] tmpResult = Regex.Split(str, regex); byte[] result = new byte[keyN]; int i = 0; foreach (string tmp in tmpResult) { result[i] = Convert.ToByte(tmp, 16); i++; } return result; } //显示结果 private string GetHexData(byte[] data, int s, int e) { string ret = string.Empty; //非负转换 for (int i = 0; i < e; i++) { if (data[s + i] < 0) data[s + i] = Convert.ToByte(Convert.ToInt32(data[s + i]) + 256); } for (int i = 0; i < e; i++) ret += data[s + i].ToString("X2"); return ret; } private string GetStatue(int Code) { string msg = ""; switch (Code) { case 0x00: msg = "命令执行成功 ....."; break; case 0x01: msg = "命令操作失败 ....."; break; case 0x02: msg = "地址校验错误 ....."; break; case 0x03: msg = "找不到已选择的端口 ....."; break; case 0x04: msg = "读写器返回超时 ....."; break; case 0x05: msg = "数据包流水号不正确 ....."; break; case 0x07: msg = "接收异常 ....."; break; case 0x0A: msg = "参数值超出范围 ....."; break; case 0x80: msg = "参数设置成功 ....."; break; case 0x81: msg = "参数设置失败 ....."; break; case 0x82: msg = "通讯超时....."; break; case 0x83: msg = "卡不存在....."; break; case 0x84: msg = "接收卡数据出错....."; break; case 0x85: msg = "未知的错误....."; break; case 0x87: msg = "输入参数或者输入命令格式错误....."; break; case 0x89: msg = "输入的指令代码不存在....."; break; case 0x8A: msg = "在对于卡块初始化命令中出现错误....."; break; case 0x8B: msg = "在防冲突过程中得到错误的序列号....."; break; case 0x8C: msg = "密码认证没通过....."; break; case 0x8F: msg = "读取器接收到未知命令....."; break; case 0x90: msg = "卡不支持这个命令....."; break; case 0x91: msg = "命令格式有错误....."; break; case 0x92: msg = "在命令的FLAG参数中,不支持OPTION 模式....."; break; case 0x93: msg = "要操作的BLOCK不存在....."; break; case 0x94: msg = "要操作的对象已经别锁定,不能进行修改....."; break; case 0x95: msg = "锁定操作不成功....."; break; case 0x96: msg = "写操作不成功....."; break; default: msg = "未知错误2....."; break; } return msg; } }
刷卡声明定义:
public Action<LoginResultDto> EventClick; private CardReader _cardReader; private string _CardReaderPort; private int _CardReaderBaudRate; private Thread _thdCardReader; private int _IntervalSec; private bool _IsRunCardReader; private string _cardNum = string.Empty; // 识别卡号码
刷卡:
#region 读卡 private void ReadCard() { try { _CardReaderPort = UtilityTablet.GetAppSetting("CardReaderPort", "COM1"); _CardReaderBaudRate = Convert.ToInt32(UtilityTablet.GetAppSetting("CardReaderBaudRate", "9600")); _IntervalSec = Convert.ToInt32(UtilityTablet.GetAppSetting("IntervalSec", "1")); //CardReader.port = _CardReaderPort; //CardReader.baudrate = _CardReaderBaudRate; _cardReader = new CardReader(_CardReaderPort, _CardReaderBaudRate); _cardReader.Conn(); _IsRunCardReader = true; _thdCardReader = new Thread(ReadCardThread); _thdCardReader.IsBackground = true; _thdCardReader.Start(); } catch (Exception ex) { ShowErrorMessage(ex.Message); } } private void ReadCardThread() { try { System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = _IntervalSec * 1000; timer.Elapsed += (sender, e) => { timer.Stop(); if (!_IsRunCardReader) return; try { string ret = _cardReader.ReadCardNo(); if (!String.IsNullOrEmpty(ret)) { _IsRunCardReader = false; byte[] TmpData = UtilityTablet.strToToHexByte(ret.Trim()); // cardNum = BitConverter.ToSingle(new byte[] { TmpData[1], TmpData[0], TmpData[3], TmpData[2] }, 0).ToString(); _cardNum = ((uint)((TmpData[3] << 24) + (TmpData[2] << 16) + (TmpData[1] << 8) + TmpData[0])).ToString(); //登录 this.BeginInvoke(new Action(() => { LoginByLoginId(_cardNum).Wait(); })); } } catch (Exception ex) { //this.BeginInvoke(new Action(() => { ShowErrorMessage(ex.Message); })); } timer.Start(); }; timer.Start(); } catch (Exception ex) { ShowErrorMessage(ex.Message); } } private void CloseReadCard() { if (_cardReader != null) { _IsRunCardReader = false; _cardReader.Close(); } } #endregion
关闭读卡串口:
private void CloseReadCard() { if (_cardReader != null) { _IsRunCardReader = false; _cardReader.Close(); } }
调用的方法:
private async Task LoginByLoginId(string loginId) //扫码后扫到的值 { try { BtnMsgShow("正在校验,请稍等......", false); var input = new LoginCardNumInput { CardNum = loginId, }; this.Cursor = Cursors.WaitCursor; //逻辑 根据扫码或刷卡number获取信息 var nHttpResponseMessage = await _Service.loginCardNumService.GetInfor(input); if (nHttpResponseMessage.IsSuccessStatusCode) { var nResponse = await nHttpResponseMessage.Content.ReadAsStringAsync(); if (!nResponse.IsNullOrEmpty()) { var nResult = (AjaxResponse)nResponse.ToJsonObject(typeof(AjaxResponse)); var nLoginResultDto = (LoginResultDto)nResult.Result.ToString().ToJsonObject(typeof(LoginResultDto)); //返回值 _LoginResult = nLoginResultDto; txt_FullName.Text = _LoginResult.FullName; } this.Cursor = Cursors.Default; BtnMsgShow("", true); } else { this.Cursor = Cursors.Default; ShowErrorMessage("卡号或工号错误"); } }
使用委托:
private void btn_confirm_Click(object sender, EventArgs e) { try { //读卡或扫码得到的信息 if (_LoginResult == null) return; //委托 EventClick?.Invoke(_LoginResult); } catch (Exception ex) { AppInfo.ShowMessageForm(ex.Message); } }
调用委托:
public void btnReadCard_Wait() { FLoginAuthenticate fLogin = new FLoginAuthenticate(); fLogin.Title = "请维修人员刷卡或扫码二维码"; fLogin.EventClick += (LoginResult) => { if (LoginResult.UserId != null) { CheckPerson.Text = LoginResult.FullName; CheckPerson.Tag = LoginResult.UserId; fLogin.DialogResult = DialogResult.Yes; fLogin.Close(); } else { AppInfo.ShowMessageForm("认证人员不正确,请重新认证!"); } }; DialogResult fResult = fLogin.ShowDialog(); if (fResult != DialogResult.Yes) return; //ReadCard(); }
窗体关闭按钮:
private void btnClose_Click(object sender, EventArgs e) { //父窗体可用到次变量 this.DialogResult = DialogResult.No; this.Close(); }
窗体关闭事件关掉串口:
private void FLoginAuthenticate_FormClosing(object sender, FormClosingEventArgs e) { CloseReadCard(); }
浙公网安备 33010602011771号