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

WinAPI 系統訊息過濾鉤子 SysMsgFilterProc 詳細指南

     編輯:Delphi

SysMsgFilterProc 回調函數概述

SysMsgFilterProc 是 Windows 系統訊息過濾鉤子(WH_SYSMSGFILTER)的回調函數。此鉤子允許應用程式監控並過濾系統層級的訊息,特別是對話方塊、訊息方塊、功能表等系統 UI 產生的訊息。它屬於全域鉤子,必須在 DLL 中實現並透過 SetWindowsHookEx 安裝。

函數原型

LRESULT CALLBACK SysMsgFilterProc(
  _In_ int    nCode,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

參數詳細說明

參數類型說明
nCodeint鉤子代碼,決定如何處理訊息:
MSGF_DIALOGBOX (0):對話方塊訊息
MSGF_MESSAGEBOX (1):訊息方塊訊息
MSGF_MENU (2):功能表訊息
MSGF_SCROLLBAR (5):捲軸訊息
MSGF_NEXTWINDOW (6):視窗切換訊息 (Alt+Tab)
wParamWPARAM訊息類型(如 WM_KEYDOWN、WM_COMMAND 等)
lParamLPARAM指向 MSG 結構的指標,包含完整訊息資訊

返回值邏輯

  • 返回 0:訊息未被處理,繼續傳遞給目標視窗程序
  • 返回非零值:訊息已被處理/攔截,系統會丟棄該訊息
  • nCode < 0:必須呼叫 CallNextHookEx 並返回其結果

WH_SYSMSGFILTER 與 WH_MSGFILTER 差異

特性WH_SYSMSGFILTERWH_MSGFILTER
範圍全系統所有執行緒僅安裝執行緒的訊息佇列
安裝需求必須在 DLL 中,注入所有進程同進程即可,無需 DLL
攔截目標系統模態對話框、訊息框、功能表應用程式自身的模態迴圈
典型用途系統級熱鍵、無障礙工具、UI 自動化應用程式內部模態對話框快捷鍵

實戰範例:攔截系統訊息方塊的 ESC 鍵 (Delphi DLL)

HookDLL.dpr

library HookDLL;

uses
  Windows,
  Messages,
  SysUtils;

{$R *.res}

var
  g_hHook: HHOOK = 0;

function SysMsgFilterProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  pMsg: PMSG;
begin
  Result := 0;
  if nCode >= 0 then
  begin
    // 僅處理訊息方塊訊息
    if nCode = MSGF_MESSAGEBOX then
    begin
      pMsg := PMSG(lParam);
      // 攔截 ESC 鍵關閉訊息方塊
      if (pMsg.message = WM_KEYDOWN) and (pMsg.wParam = VK_ESCAPE) then
      begin
        // 這裡可以記錄日誌、播放聲音、或彈出自定義確認對話框
        OutputDebugString('SysMsgFilter: ESC pressed on MessageBox, intercepted!');
        Result := 1; // 攔截,阻止訊息方塊關閉
        Exit;
      end;
    end;
  end;
  Result := CallNextHookEx(g_hHook, nCode, wParam, lParam);
end;

procedure InstallHook; stdcall;
begin
  if g_hHook = 0 then
    g_hHook := SetWindowsHookEx(WH_SYSMSGFILTER, @SysMsgFilterProc, HInstance, 0);
end;

procedure UninstallHook; stdcall;
begin
  if g_hHook <> 0 then
  begin
    UnhookWindowsHookEx(g_hHook);
    g_hHook := 0;
  end;
end;

exports
  InstallHook,
  UninstallHook;

begin
  DisableThreadLibraryCalls(HInstance);
end.

主程式調用

unit MainUnit;

interface

uses Windows, Forms, StdCtrls, Controls;

type
  TForm1 = class(TForm)
    btnShowMsgBox: TButton;
    btnInstallHook: TButton;
    btnUninstallHook: TButton;
    procedure btnShowMsgBoxClick(Sender: TObject);
    procedure btnInstallHookClick(Sender: TObject);
    procedure btnUninstallHookClick(Sender: TObject);
  private
    procedure InstallHook; external 'HookDLL.dll' name 'InstallHook';
    procedure UninstallHook; external 'HookDLL.dll' name 'UninstallHook';
  end;

implementation

{$R *.dfm}

procedure TForm1.btnShowMsgBoxClick(Sender: TObject);
begin
  MessageBox(Handle, '按 ESC 鍵測試攔截效果', '系統訊息方塊', MB_OK or MB_ICONINFORMATION);
end;

procedure TForm1.btnInstallHookClick(Sender: TObject);
begin
  InstallHook;
  ShowMessage('SysMsgFilter 鉤子已安裝');
end;

procedure TForm1.btnUninstallHookClick(Sender: TObject);
begin
  UninstallHook;
  ShowMessage('SysMsgFilter 鉤子已移除');
end;

end.

進階應用:模態對話框鍵盤導航增強

透過 MSGF_DIALOGBOX 代碼,可以為所有系統對話框(如檔案開啟/儲存對話框、列印對話框)添加自定義快捷鍵:

if nCode = MSGF_DIALOGBOX then
begin
  pMsg := PMSG(lParam);
  if (pMsg.message = WM_KEYDOWN) then
  begin
    case pMsg.wParam of
      VK_F1: // F1 顯示線上說明
        begin
          // 發送自定義訊息給主程式顯示說明
          PostMessage(FindWindow('MyAppClass', nil), WM_USER + 100, 0, 0);
          Result := 1;
          Exit;
        end;
      VK_F5: // F5 重新整理檔案列表
        begin
          // 模擬點擊「重新整理」按鈕
          PostMessage(pMsg.hwnd, WM_COMMAND, MAKEWPARAM(ID_REFRESH, BN_CLICKED), 0);
          Result := 1;
          Exit;
        end;
    end;
  end;
end;

注意事項與限制

  1. DLL 必須與目標進程位數一致:32 位 DLL 只能注入 32 位進程,64 位同理。
  2. Session 隔離:服務進程(Session 0)安裝的全域鉤子無法攔截使用者 Session 中的 UI 訊息。
  3. 效能影響:系統訊息過濾鉤子會影響所有模態對話框的回應速度,回調必須極度精簡。
  4. UAC 完整性等級:低完整性進程(如 IE Protected Mode)無法注入高完整性進程。
  5. Windows 版本差異:Vista 之後引入 UIPI (User Interface Privilege Isolation),進一步限制跨完整性等級的鉤子注入。

除錯建議

  • 使用 OutputDebugString 配合 DebugView 監控回調觸發情況
  • 在 DLL 導出函數中添加 DisableThreadLibraryCalls 減少載入/卸載通知開銷
  • 記錄 nCode 值分佈,確認實際攔截到的訊息類型
  • 測試時嘗試在不同權限、不同 Session 的應用程式中觸發模態對話框

相關 API 快速查閱

  • SetWindowsHookEx(WH_SYSMSGFILTER, ...) - 安裝系統訊息過濾鉤子
  • CallNextHookEx - 傳遞給鉤子鏈中下一個處理程序
  • UnhookWindowsHookEx - 移除鉤子
  • GetMessage / PeekMessage - 訊息迴圈相關
  • IsDialogMessage - 系統內部處理對話框鍵盤導航的 API
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved