首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實現螢幕鍵盤 ScreenKeyboard(二)——SetWindowsHookEx 安裝全域鉤子完整實現

     編輯:關於C語言

鉤子類型與範圍

  • 局部鉤子:僅攔截本進程執行緒事件
  • 遠端鉤子 (全域):攔截所有進程事件,需 DLL 封裝
  • 執行緒鉤子:針對特定執行緒

全域鉤子安裝必要條件

  1. 鉤子程序放在 DLL 中
  2. LoadLibrary 取得 DLL 模組控制代碼
  3. GetProcAddress 取得鉤子程序位址
  4. SetWindowsHookEx 傳入模組控制代碼、執行緒 ID=0 (關聯所有執行緒)

C# 平台呼叫實現


public void Start(bool installMouseHook, bool installKeyboardHook)
{
    // 滑鼠鉤子 (WH_MOUSE_LL = 14)
    if (hMouseHook == IntPtr.Zero && installMouseHook)
    {
        MouseHookProcedure = new HookProc(MouseHookProc);
        hMouseHook = SetWindowsHookEx(
            WH_MOUSE_LL,
            MouseHookProcedure,
            Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
            0);
        
        if (hMouseHook == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            Stop(true, false, false);
            throw new Win32Exception(errorCode);
        }
    }

    // 鍵盤鉤子 (WH_KEYBOARD_LL = 13)
    if (hKeyboardHook == IntPtr.Zero && installKeyboardHook)
    {
        KeyboardHookProcedure = new HookProc(KeyboardHookProc);
        hKeyboardHook = SetWindowsHookEx(
            WH_KEYBOARD_LL,
            KeyboardHookProcedure,
            Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
            0);
        
        if (hKeyboardHook == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            Stop(false, true, false);
            throw new Win32Exception(errorCode);
        }
    }
}

關鍵技術細節

  • WH_MOUSE_LL / WH_KEYBOARD_LL:低階鉤子,不需 DLL 分離,C# 直接安裝全域鉤子
  • Marshal.GetHINSTANCE:取得當前組件模組控制代碼,替代 LoadLibrary
  • Assembly.GetExecutingAssembly().GetModules()[0]:取得主模組
  • 執行緒 ID = 0:關聯所有桌面執行緒 (全域)
  • 委派持有:MouseHookProcedure、KeyboardHookProcedure 必須為成員變數,防止 GC 回收
  • 失敗回滾:安裝失敗時呼叫 Stop 清理已安裝鉤子
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved