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

WinAPI 鉤子回調:CallWndProcRetProc 詳細解析

     編輯:Delphi

CallWndProcRetProc 回調函數

CallWndProcRetProc 配合 WH_CALLWNDPROCRET 鉤子類型,在目標視窗程序處理完 SendMessage 發送的訊息並返回後被呼叫。與 WH_CALLWNDPROC (發送前) 形成前後夾擊,可完整觀測同步訊息的完整生命週期。

函數原型

function CallWndProcRetProc(
  nCode: Integer;    // 鉤子代碼
  wParam: WPARAM;    // 保留,通常 0
  lParam: LPARAM     // 指向 CWPRETSTRUCT 結構
): LRESULT; stdcall;

CWPRETSTRUCT 結構詳解

type
  tagCWPRETSTRUCT = record
    lResult: LRESULT;  // 視窗程序返回值 (SendMessage 的返回值)
    message: UINT;     // 訊息 ID
    wParam: WPARAM;    // 訊息參數 1
    lParam: LPARAM;    // 訊息參數 2
    hwnd: HWND;        // 目標視窗句柄
  end;

關鍵差異:lResult 欄位包含視窗程序實際返回的結果,這是 WH_CALLWNDPROC (CWPSTRUCT) 沒有的。

觸發條件與範圍

  • 僅攔截 SendMessage (同步發送),PostMessage (非同步) 不觸發。
  • 系統級 (dwThreadId=0) 監控所有線程的 SendMessage;線程級僅監控目標線程。
  • 跨進程 SendMessage 同樣會觸發系統級鉤子 (需 DLL)。

典型應用場景

  • 訊息返回值分析:記錄關鍵訊息 (如 WM_QUERYENDSESSION) 的返回值,診斷關機攔截失敗。
  • 修正/補充返回值:雖無法修改已返回的 lResult (傳值),但可記錄供事後分析。
  • 效能測量:配合 WH_CALLWNDPROC 計算 SendMessage 往返耗時。
  • UI 自動化驗證:確認特定操作 (如按鈕點擊 BM_CLICK) 是否正確返回。

系統級部署範例 (DLL)

{ HookDll.dpr }
library HookDll;
uses Windows, SysUtils;

var hHook: HHOOK = 0;
    LogFile: TextFile;

function CallWndProcRetProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var p: PCWPRETSTRUCT;
begin
  if nCode = HC_ACTION then
  begin
    p := PCWPRETSTRUCT(lParam);
    // 僅記錄特定訊息減少噪音
    if p.message = WM_DESTROY then
    begin
      AssignFile(LogFile, 'C:\Temp\HookLog.txt');
      if FileExists('C:\Temp\HookLog.txt') then Append(LogFile) else Rewrite(LogFile);
      WriteLn(LogFile, Format('[%s] HWND:%x Msg:WM_DESTROY Result:%d',
        [DateTimeToStr(Now), p.hwnd, p.lResult]));
      CloseFile(LogFile);
    end;
  end;
  Result := CallNextHookEx(hHook, nCode, wParam, lParam);
end;

function InstallHook: Boolean; stdcall;
begin
  hHook := SetWindowsHookEx(WH_CALLWNDPROCRET, @CallWndProcRetProc, HInstance, 0);
  Result := hHook <> 0;
end;

function UninstallHook: Boolean; stdcall;
begin
  if hHook <> 0 then begin Result := UnhookWindowsHookEx(hHook); if Result then hHook := 0; end else Result := True;
end;

exports InstallHook, UninstallHook;
begin
end.

WH_CALLWNDPROC vs WH_CALLWNDPROCRET 對比

特性WH_CALLWNDPROC (前)WH_CALLWNDPROCRET (後)
觸發時機SendMessage 進入目標視窗程序前視窗程序返回後,SendMessage 返回前
結構體CWPSTRUCT (無 lResult)CWPRETSTRUCT (含 lResult)
可修改訊息是 (修改 wParam/lParam 影響處理)否 (訊息已處理完畢)
可獲取返回值否是 (lResult)
典型用途訊息過濾、參數修改、攔截返回值審計、效能測量、驗證

注意事項

  • 同步訊息鏈:SendMessage 會阻塞發送線程直到返回,鉤子回調在目標線程上下文執行,不可阻塞 (不得呼叫 SendMessage、等待同步物件)。
  • 系統級需 DLL:跨進程監控必須用 DLL,EXE 僅能線程級。
  • 噪音極大:系統每秒數萬次 SendMessage,務必在回調開頭快速過濾 message,只處理關心的訊息。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved