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數據結構

相關文章
相關標籤/搜索