winform鍵盤全局與線程Hook


定義數據結構

        /// <summary>
        /// 聲明鍵盤鈎子的封送結構類型
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            public int vkCode;//表示一個1到254間的虛擬鍵盤碼
            public int scanCode;//表示硬件掃描碼
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

聲明Hook相關方法

        //使用WINDOWS API函數代替獲取當前實例的函數,防止鈎子失效
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
        //安裝鈎子
        [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 int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
        //卸載鈎子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        // 取得當前線程編號(線程鈎子需要用到)
        [DllImport("kernel32.dll")]
        static extern int GetCurrentThreadId();

Hook攔截方法

全局Hook

        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
            {
                KeyboardHookStruct MyKBHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
 
                //引發OnKeyDownEvent
                if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                {
                    Keys keyData = (Keys)MyKBHookStruct.vkCode;
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    OnKeyDownEvent(this, e);
                }
            }
            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }

線程Hook

 private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
            {
               
                //引發OnKeyDownEvent
                if (OnKeyDownEvent != null && nCode==0)
                {
                    Keys keyData = (Keys)wParam;
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    OnKeyDownEvent(this, e);
                }
            }
            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }

全局/線程Hook參數結構區別

線程Hook KeyboardHookProc函數的各個參數意義如下:

nCode    消息的類型,分HC_ACTION和HC_NOREMOVE

wParam    按鍵的虛擬鍵碼 

lParam    按鍵的相關參數信息,包括重復時間、按鍵的狀態(按下或彈起)等

全局Hook KeyboardHookProc函數的各個參數意義如下:

nCode    消息的類型,有HC_ACTION

wParam    按鍵的狀態(按下或彈起)WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP

lParam    指向KeyboardHookStruct結構的指針,該結構包含了按鍵的詳細信息。

添加Hook

全局Hook

        public void Start()
        {
            if (hKeyboardHook == 0)
            {
                KeyboardHookProcedure = new HookProc(KeyboardHookProc);
                using (System.Diagnostics.Process curProcess = System.Diagnostics.Process.GetCurrentProcess())
                using (System.Diagnostics.ProcessModule curModule = curProcess.MainModule)
                    hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);
 
                if (hKeyboardHook == 0)
                {
                    Stop();
                    throw new Exception("Set GlobalKeyboardHook failed!");
                }
            }
        }

線程Hook

   public void Start()
        {
            if (hKeyboardHook == 0)
            {
                KeyboardHookProcedure = new HookProc(KeyboardHookProc);
                hKeyboardHook = SetWindowsHookEx(2, KeyboardHookProcedure,  IntPtr.Zero, GetCurrentThreadId());
 
                if (hKeyboardHook == 0)
                {
                    Stop();
                    throw new Exception("Set GlobalKeyboardHook failed!");
                }
            }
        }

注:idHook 鈎子類型,即確定鈎子監聽何種消息
線程鈎子監聽鍵盤消息應設為2,全局鈎子監聽鍵盤消息應設為13
線程鈎子監聽鼠標消息應設為7,全局鈎子監聽鼠標消息應設為14


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM