.Net全局鉤子實現USB掃碼槍無焦點狀態下掃入支付碼(支付寶、微信)

掃碼識別實現方法

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace CashierProject.ManageUtils
{
    /// <summary>
    /// 掃碼識別
    /// </summary>
    public class ScanHook
    {        
        public List<string> matchString { get; set; }//驗證是否正確的收款碼等信息
        public const int WM_KEYDOWN = 256;
        public const int WM_KEYUP = 257;
        public const int WM_SYSKEYDOWN = 260;
        public const int WM_SYSKEYUP = 261;
        private int hKeyboardHook;
        private static HookProc hookproc;
        private static ScanHook instance;
        public delegate void ScanerDelegate(string code);
        private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
        public event ScanerDelegate ScanerEvent;
        private int delayInputTime = 150;
        private int delayOutputTime = 1000;
        private List<EventMsg> keys = new List<EventMsg>();
        private int last;
        private int first;
        private bool isPause;
        private Thread delayThread;
        private bool isBreak = true;
        private object lockObject = new object();
        public struct EventMsg
        {
            public int keyCode;
            public int paramL;
            public int paramH;
            public int Time;
            public int hwnd;
            public int keyType;
        }
        public struct Result
        {
            public List<EventMsg> keyCodes;
            public string result;
            public bool isIntercept;
            public bool isScan;
        }
        public static ScanHook getInstance()
        {
            if (instance == null)
            {
                instance = new ScanHook();
            }
            return instance;
        }
        /// <summary>
        /// 加載鉤子
        /// </summary>
        /// <param name="idHook"></param>
        /// <param name="lpfn"></param>
        /// <param name="hInstance"></param>
        /// <param name="threadId"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        /// <summary>
        /// 卸載鉤子
        /// </summary>
        /// <param name="idHook"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        /// <summary>
        /// 當一個文件被映射到調用進程的地址空間時,GetModuleHandle函數得到其中某一模塊的句柄
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);


        public void SetDelayInputTime(int delayTime)
        {
            delayInputTime = delayTime;
        }
       
        public void SetDelayOutputTime(int delayTime)
        {
            delayOutputTime = delayTime;
        }
        /// <summary>
        /// 開啓鍵盤監聽
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (hKeyboardHook == 0)
            {
                hookproc = new HookProc(KeyboardHookProc);
                IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
                hKeyboardHook = SetWindowsHookEx(13, hookproc, moduleHandle, 0);
                return hKeyboardHook != 0;
            }
            Stop();
            return Start();
        }
        /// <summary>
        /// 關閉鍵盤監聽
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            if (hKeyboardHook != 0)
            {
                bool flag =UnhookWindowsHookEx(hKeyboardHook);
                if (flag)
                {
                    hKeyboardHook = 0;
                }
                return flag;
            }
            return true;
        }

        /// <summary>
        /// 監聽鍵盤按鍵
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
        {
           EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
            msg.keyType = wParam;
            Result result = Add(msg);
            if (result.isIntercept && ScanerEvent != null && result.isScan && !string.IsNullOrEmpty(result.result))
            {
                if (matchString != null && matchString.Count > 0)
                {
                    bool flag = false;
                    foreach (string match in matchString)
                    {
                        if (IsMatchRegular(result.result, match))
                        {
                            flag = true;
                            break;
                        }
                    }
                    if (flag)
                    {
                        ScanerEvent.BeginInvoke(result.result, null, null);//執行掃碼事件
                    }
                    else
                    {
                        Input(result.keyCodes);
                    }
                }
                else
                {
                    Input(result.keyCodes);
                }
            }
            if (!result.isIntercept)
            {
                return 0;
            }
            return 1;
        }
        public Result Add(EventMsg msg)
        {
            Result result2;
            lock (this)
            {
                Result result = default(Result);
                if (isPause)
                {
                    result.isIntercept = false;
                    result2 = result;
                }
                else
                {
                    bool flag2 = msg.Time - last < delayInputTime;
                    last = msg.Time;
                    if (IsNumberCode(msg))
                    {
                        if (keys.Count == 0)
                        {
                            first = msg.Time;
                        }
                        keys.Add(msg);
                        DelayInput();
                        result.isIntercept = true;
                        result2 = result;
                    }
                    else
                    {
                        if (msg.keyCode == 13 && keys.Count > 0 && flag2)
                        {
                            keys.Add(msg);
                            result.keyCodes = new List<EventMsg>(keys);
                            result.result = GetResult();
                            result.isIntercept = true;
                            if (msg.keyType == 257)
                            {
                                keys.Clear();
                                result.isScan = true;
                            }
                        }
                        else
                        {
                            Input(keys);
                            keys.Clear();
                            result.isIntercept = false;
                        }
                        result2 = result;
                    }
                }
            }
            return result2;
        }
        private void DelayInput()
        {
            isBreak = true;
            if (delayThread == null)
            {
                delayThread = new Thread(new ThreadStart(ThreadStart));
                delayThread.Start();
            }
        }
        /// <summary>
        /// 開啓線程
        /// </summary>
        private void ThreadStart()
        {
            for (; ; )
            {
                if (isBreak)
                {
                    isBreak = false;
                }
                else
                {
                    Thread.Sleep(delayInputTime);
                    if (isBreak)
                    {
                        isBreak = false;
                    }
                    else
                    {
                        Input(keys);
                        keys.Clear();
                    }
                }
            }
        }
        /// <summary>
        /// 模擬鍵盤輸入掃碼結果
        /// </summary>
        /// <param name="pressList"></param>
        public void Input(List<EventMsg> pressList)
        {
            object obj = lockObject;
            lock (obj)
            {
                try
                {
                    List<EventMsg> list = new List<EventMsg>(pressList);
                    if (list.Count > 0)
                    {
                        isPause = true;
                    }
                    foreach (EventMsg eventMsg in list)
                    {
                        if (eventMsg.keyType == 256)
                        {
                            KeyBoardUtil.DownKey(eventMsg.keyCode);
                        }
                        else if (eventMsg.keyType == 257)
                        {
                            KeyBoardUtil.UpKey(eventMsg.keyCode);
                        }
                    }
                    isPause = false;
                }
                catch
                {
                }
            }
        }
        /// <summary>
        /// 根據鍵盤獲取對應的數字
        /// </summary>
        /// <returns></returns>
        private string GetResult()
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (EventMsg eventMsg in keys)
            {
                if (eventMsg.keyType == 256)
                {
                    switch (eventMsg.keyCode)
                    {
                        case 48:
                            stringBuilder.Append("0");
                            break;
                        case 49:
                            stringBuilder.Append("1");
                            break;
                        case 50:
                            stringBuilder.Append("2");
                            break;
                        case 51:
                            stringBuilder.Append("3");
                            break;
                        case 52:
                            stringBuilder.Append("4");
                            break;
                        case 53:
                            stringBuilder.Append("5");
                            break;
                        case 54:
                            stringBuilder.Append("6");
                            break;
                        case 55:
                            stringBuilder.Append("7");
                            break;
                        case 56:
                            stringBuilder.Append("8");
                            break;
                        case 57:
                            stringBuilder.Append("9");
                            break;
                    }
                }
            }
            return stringBuilder.ToString();
        }
        /// <summary>
        /// 正則驗證
        /// </summary>
        /// <param name="s"></param>
        /// <param name="match"></param>
        /// <returns></returns>
        public static bool IsMatchRegular(string s, string match)
        {
            bool result;
            try
            {
                result = new Regex(match).IsMatch(s);
            }
            catch
            {
                result = false;
            }
            return result;
        }
        private bool IsNumberCode(EventMsg msg)
        {
            return msg.keyCode >= 48 && msg.keyCode <= 57;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CashierProject.ManageUtils
{
    /// <summary>
    /// 鍵盤輸入模擬
    /// </summary>
    public class KeyBoardUtil
    {
        /// <summary>
        /// 鼠標事件枚舉數據
        /// </summary>
        private enum MouseEventFlag : uint
        {
            Move = 1U,
            LeftDown,
            LeftUp = 4U,
            RightDown = 8U,
            RightUp = 16U,
            MiddleDown = 32U,
            MiddleUp = 64U,
            XDown = 128U,
            XUp = 256U,
            Wheel = 2048U,
            VirtualDesk = 16384U,
            Absolute = 32768U
        }
        /// <summary>
        /// 模擬鍵盤輸入事件
        /// </summary>
        /// <param name="bVk"></param>
        /// <param name="bScan"></param>
        /// <param name="dwFlags"></param>
        /// <param name="dwExtraInfo"></param>
        [DllImport("user32.dll", SetLastError = true)]
        private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
        /// <summary>
        /// 模擬鼠標事件
        /// </summary>
        /// <param name="flags"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="data"></param>
        /// <param name="extraInfo"></param>
        [DllImport("user32.dll")]
        private static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);
        /// <summary>
        /// 把光標移到屏幕的指定位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern int SetCursorPos(int x, int y);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        public static void PressKey(Keys key)
        {
            DownKey(key);
            UpKey(key);
        }
       /// <summary>
       /// 
       /// </summary>
       /// <param name="keys"></param>
        public static void PressKey(Keys[] keys)
        {
            for (int i = 0; i < keys.Length; i++)
            {
                DownKey(keys[i]);
            }
            Array.Reverse(keys);
            for (int i = 0; i < keys.Length; i++)
            {
                UpKey(keys[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        public static void PressKey(int key)
        {
            PressKey((Keys)Enum.ToObject(typeof(Keys), key));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        private static void UpKey(Keys key)
        {
            keybd_event(key, 0, 2U, 0U);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        private static void DownKey(Keys key)
        {
            keybd_event(key, 0, 0U, 0U);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        public static void UpKey(int key)
        {
            UpKey((Keys)Enum.ToObject(typeof(Keys), key));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        public static void DownKey(int key)
        {
            DownKey((Keys)Enum.ToObject(typeof(Keys), key));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static void MouseClick(int x, int y)
        {
            SetCursorPos(x, y);
            mouse_event(MouseEventFlag.LeftDown, x, y, 0U, UIntPtr.Zero);
            mouse_event(MouseEventFlag.LeftUp, x, y, 0U, UIntPtr.Zero);
        }
        
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cashier.Model;
using CommonUtils;

namespace CashierProject.ManageUtils
{
    public class ScanUtil: MarshalByRefObject
    {
        static string scanCode = "";
        /// <summary>
        /// 開啓/關閉掃碼監聽
        /// </summary>
        public static void OpenOrStopScaner()
        {
            List<string> list = new List<string>();
            list.Add("^((10)|(11)|(12)|(13)|(14)|(15))\\d{16}$");//微信支付碼驗證規則
            list.Add("^((25)|(26)|(27)|(28)|(29)|(30))\\d{14,22}$");//支付寶付款碼驗證規則
            //list.Add("^[0-9]*$");//用於測試的驗證規則  只能是整數
            ScanHook.getInstance().matchString = list;
            ScanHook.getInstance().ScanerEvent -= new ScanHook.ScanerDelegate(RequestCode);
            ScanHook.getInstance().ScanerEvent += new ScanHook.ScanerDelegate(RequestCode);
 ScanHook.getInstance().SetDelayInputTime(150);
                ScanHook.getInstance().Start();
                //ScanHook.getInstance().Stop();
        }
        /// <summary>
        /// 收款碼
        /// </summary>
        /// <param name="result"></param>
        private static void RequestCode(string result)
        {
            scanCode = result;
            //需要執行的事件
        }
    }
}

調用示例(只需在程序啓動時調用一次就可以)

ManageUtils.ScanUtil.OpenOrStopScaner();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章