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

VC++ 鉤子與 DLL 深度解析(下):鍵盤/滑鼠鉤子實作與 DLL 導出函數

     編輯:VC 教學

DLL 導出函數:安裝與移除鉤子

鉤子程序必須置於 DLL 中以實現系統級攔截。以下為核心導出函數:

1. 安裝鉤子

__declspec(dllexport) BOOL SetMyHook(HWND hWndServer)
{
    if (hWndServer == NULL) return FALSE;
    hWndServer = hWnd;  // 全域變數儲存接收視窗
    hook = SetWindowsHookEx(WH_GETMESSAGE, MsgHook, hInst, 0);
    return (hook != NULL);
}

2. 移除鉤子

__declspec(dllexport) BOOL ClearMyHook(HWND hWnd)
{
    if (hWnd != hWndServer) return FALSE;
    BOOL unhooked = UnhookWindowsHookEx(hook);
    if (unhooked) hWndServer = NULL;
    return unhooked;
}

鉤子回呼函數

static LRESULT CALLBACK MsgHook(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode < 0)  // 必須傳遞給下一個鉤子
        return CallNextHookEx(hook, nCode, wParam, lParam);

    LPMSG msg = (LPMSG)lParam;  // WH_GETMESSAGE: lParam 指向 MSG 結構

    // 攔截滑鼠移動訊息(客戶區與非客戶區)
    if (msg->message == WM_MOUSEMOVE || msg->message == WM_NCMOUSEMOVE)
    {
        // 使用 PostMessage 非同步通知主視窗,避免阻塞鉤子鏈
        PostMessage(hWndServer, UWM_MOUSEMOVE, 0, 0);
    }

    return CallNextHookEx(hook, nCode, wParam, lParam);
}

主應用程式接收通知

1. 註冊自訂訊息

// 標頭檔
#define UWM_MOUSEMOVE_MSG "MyApp_MouseMove"
UINT UWM_MOUSEMOVE = ::RegisterWindowMessage(UWM_MOUSEMOVE_MSG);

2. 訊息映射

BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
    ON_REGISTERED_MESSAGE(UWM_MOUSEMOVE, OnMyMouseMove)
END_MESSAGE_MAP()

3. 處理函數

LRESULT CMyApp::OnMyMouseMove(WPARAM, LPARAM)
{
    CPoint pt;
    GetCursorPos(&pt);
    // 這裡處理滑鼠座標,如更新 UI、追蹤軌跡等
    return 0;
}

完整範例:貓捉老鼠遊戲

示範程式建立全域 WH_GETMESSAGE 鉤子,攔截滑鼠移動,主視窗接收通知後移動「貓」的圖片追蹤滑鼠「老鼠」。當距離足夠近時觸發捕捉動畫。

貓捉老鼠示範截圖

關鍵技術點總結

  • DLL 導出:__declspec(dllexport) 讓 EXE 可呼叫安裝/移除函數。
  • 共享資料區:#pragma data_seg("SHARED") 讓 hWndServer、hook 在所有載入 DLL 的進程間共享。
  • CallNextHookEx:務必呼叫以維持鉤子鏈,否則系統其他鉤子失效。
  • PostMessage vs SendMessage:鉤子中必須用 PostMessage 非同步通知,SendMessage 會阻塞導致系統卡頓。
  • 協助函數:ClipCursor 限制滑鼠範圍、SetCapture 捕捉滑鼠、區域裁剪、雙緩衝繪圖等輔助技巧。

編譯與部署注意事項

  1. DLL 需與 EXE 位於同一目錄,或系統路徑中。
  2. 32 位元 DLL 僅能注入 32 位元進程,64 位元同理。
  3. 系統級鉤子(WH_KEYBOARD_LL、WH_MOUSE_LL)不需 DLL,但延遲較高;全域鉤子(WH_GETMESSAGE、WH_KEYBOARD)需 DLL 且目標進程必須有訊息迴圈。
  4. 簽署 DLL 可避免殺毒軟體誤報。
  5. 掌握鉤子與 DLL 協作模式,即可實現全域熱鍵、滑鼠手勢、自動化測試、螢幕錄製等系統級功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved