用於移除先前由 SetWindowsHookEx 安裝的鉤子,釋放系統資源,恢復正常訊息流向。每個成功安裝的鉤子都必須在適當時機(如程式結束、卸載 DLL、停用功能)呼叫此函數,否則會導致鉤子鏈殘留、記憶體洩漏甚至系統不穩定。
function UnhookWindowsHookEx(
hhk: HHOOK // SetWindowsHookEx 返回的鉤子句柄
): BOOL; stdcall; // TRUE 成功,FALSE 失敗
OnDestroy 或 FormClose 中呼叫。DLL_PROCESS_DETACH 入口點呼叫,確保進程卸載 DLL 時自動清理。SetWindowsHookEx 失敗(返回 0),切勿 呼叫 UnhookWindowsHookEx(0),會導致存取違規。unit HookUnit;
interface
uses Windows;
var
hHook: HHOOK = 0;
hInstance: HINST = 0;
function KeyboardProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if nCode = HC_ACTION then
// 處理鍵盤事件...
Result := CallNextHookEx(hHook, nCode, wParam, lParam);
end;
function InstallHook: Boolean;
begin
hHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, hInstance, 0);
Result := hHook <> 0;
end;
function UninstallHook: Boolean;
begin
if hHook <> 0 then
begin
Result := UnhookWindowsHookEx(hHook);
if Result then hHook := 0;
end
else Result := True;
end;
implementation
end.
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| UnhookWindowsHookEx 返回 FALSE | 句柄無效、已被釋放、或非當前進程安裝 | 檢查 hHook 是否為 SetWindowsHookEx 原始返回值,確保同進程呼叫 |
| 程式結束後鉤子仍生效 | 未正確呼叫 UnhookWindowsHookEx | 在 FormDestroy / DLL_PROCESS_DETACH 強制清理 |
| 系統變慢、輸入延遲 | 鉤子鏈過長或回調耗時 | 精簡回調邏輯,避免在鉤子中做 I/O、同步等待 |
每一個 SetWindowsHookEx 都必須配對一個 UnhookWindowsHookEx。 這是 Windows 鉤子編程的鐵律,違反者必受其害。