HHOOK SetWindowsHookExA(
[in] int idHook,
[in] HOOKPROC lpfn,
[in] HINSTANCE hmod,
[in] DWORD dwThreadId
[in] idHook
類型:int
要安裝的攔截程序類型。 此參數可以是下列其中一個值。
[in] lpfn
類型:HOOKPROC
攔截程式的指標。 如果 dwThreadId 參數為零,或指定由不同進程建立的線程標識碼,lpfn 參數必須指向 DLL 中的攔截程式。 否則,lpfn 可以指向與目前進程相關聯之程式代碼中的攔截程式。
[in] hmod
類型:HINSTANCE
DLL 的句柄,其中包含由 lpfn 參數所指向的攔截程式。 如果 dwThreadId 參數指定目前進程所建立的線程,而且攔截程式位於與目前進程相關聯的程式代碼內,hMod 參數必須設定為 NULL。
[in] dwThreadId
類型:DWORD
要與勾點程式相關聯之線程的標識碼。 針對傳統型應用程式,如果此參數為零,攔截程式會與在與呼叫線程相同的桌面上執行的所有現有線程相關聯。 針對 Windows 市集應用程式,請參閱一節。
類型:HHOOK
如果函式成功,傳回值就是攔截程式的句柄。
如果函式失敗,則傳回值 NULL。 若要取得擴充的錯誤資訊,請呼叫 GetLastError。
SetWindowsHookEx 可用來將 DLL 插入另一個進程。 32 位 DLL 無法插入 64 位進程,而 64 位 DLL 無法插入 32 位進程。 如果應用程式需要在其他進程中使用攔截,則需要將32位應用程式呼叫 SetWindowsHookEx,將32位 DLL 插入32位進程,而64位應用程式呼叫 SetWindowsHookEx 將 64 位 DLL 插入 64 位進程。 32 位和 64 位 DLL 必須有不同的名稱。
因為攔截會在應用程式的內容中執行,所以它們必須符合應用程式的「位」。 如果 32 位應用程式在 64 位 Windows 上安裝全域攔截,則會將 32 位勾點插入每個 32 位進程(通常會套用安全性界限)。 在64位進程中,線程仍標示為「已連結」。不過,由於32位應用程式必須執行攔截程式碼,因此系統會在連結應用程式的內容中執行攔截;具體來說,在呼叫 SetWindowsHookEx的線程上。 這表示連結應用程式必須繼續提取訊息,否則可能會封鎖64位進程的正常運作。
如果64位應用程式在64位 Windows 上安裝全域攔截,則會將64位攔截插入每個64位進程,而所有32位進程都會使用連結應用程式的回呼。
若要攔截 64 位 Windows 安裝桌面上的所有應用程式,請安裝 32 位全域攔截和 64 位全域攔截,每個鏈接程式各有一個,而且請務必在連結應用程式中保留提取訊息,以避免封鎖正常運作。 如果您已經有 32 位全域連結應用程式,且不需要在每個應用程式的內容中執行,您可能不需要建立 64 位版本。
如果 hMod 參數 NULL,且 dwThreadId 參數為零,或指定另一個進程所建立之線程的標識符,就可能發生錯誤。
呼叫 CallNextHookEx 函式 函式以鏈結至下一個攔截程式是選擇性的,但強烈建議使用;否則,已安裝勾點的其他應用程式將不會收到攔截通知,因此的行為可能會不正確。 除非您絕對需要防止其他應用程式看到通知,否則您應該呼叫 CallNextHookEx。
在終止之前,應用程式必須呼叫 UnhookWindowsHookEx 函式 函式,以釋放與勾點相關聯的系統資源。
勾點的範圍取決於勾點類型。 某些勾點只能設定為全域範圍;其他人也可以只針對特定線程設定,如下表所示。
WH_CALLWNDPROC
線程或全域
WH_CALLWNDPROCRET
線程或全域
WH_CBT
線程或全域
WH_DEBUG
線程或全域
WH_FOREGROUNDIDLE
線程或全域
WH_GETMESSAGE
線程或全域
WH_JOURNALPLAYBACK
WH_JOURNALRECORD
WH_KEYBOARD
線程或全域
WH_KEYBOARD_LL
WH_MOUSE
線程或全域
WH_MOUSE_LL
WH_MSGFILTER
線程或全域
WH_SHELL
線程或全域
WH_SYSMSGFILTER
針對指定的攔截類型,會先呼叫線程攔截,然後再呼叫全域攔截。 請注意,WH_MOUSE、WH_KEYBOARD、WH_JOURNAL*、WH_SHELL和低階攔截可以在安裝攔截的線程上呼叫,而不是處理攔截的線程。 針對這些攔截,如果 32 位勾點在勾點鏈結中的 64 位攔截之前,可能會呼叫 32 位和 64 位攔截。
全域攔截是共用資源,而安裝鏈接會影響與呼叫線程相同的桌面中的所有應用程式。 所有全域攔截函式都必須在連結庫中。 全域攔截應限制為特殊用途應用程式,或在應用程式偵錯期間作為開發輔助。 不再需要勾點的連結庫應該移除其攔截程式。
Windows 市集應用程式開發 如果 dwThreadId 為零,則 Windows 市集應用程式進程和 Windows 執行時間訊息代理程式不會在進程內載入視窗勾點 DLL,除非它們是由 UIAccess 行程安裝(輔助功能工具)。 這些攔截的通知會在安裝程式的線程上傳遞:
WH_JOURNALPLAYBACK
WH_JOURNALRECORD
WH_KEYBOARD
WH_KEYBOARD_LL
WH_MOUSE
WH_MOUSE_LL
此行為類似於當攔截 DLL 與目標應用程式進程之間有架構不符的情況,例如,當攔截 DLL 為 32 位,而應用程式進程 64 位時,會發生什麼情況。
如需範例,請參閱 安裝和釋放攔截程式。
winuser.h 標頭會根據 UNICODE 預處理器常數的定義,將 SetWindowsHookEx 定義為自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程序代碼,可能會導致編譯或運行時間錯誤不符。 如需詳細資訊,請參閱函式原型的 慣例。