我正在一个 dll 中构建一个日志系统,其主要任务是捕获目标应用程序的一些特定 Windows 消息并执行一些任务。WndProc
但不幸的是,方法 ( )只捕获了一条消息WM_GETMINMAXINFO
。我错过了什么?为什么不是所有的 windows 消息都写入日志?
这是演示该问题的最小示例代码
动态链接库
library LogDll;
uses
Winapi.Windows,
Winapi.Messages,
System.IOUtils,
System.SysUtils,
System.Classes;
{$R *.res}
type
TLogInspector = class
private
WndHandle: THandle;
ProcAddrInst: Pointer;
OrgWndProc: Pointer;
protected
function CallOrgWndProc(Message: TMessage): LRESULT;
procedure WndProc(var Message: TMessage); virtual;
public
constructor Create(AHandle: THandle); virtual;
end;
var
MainHook: HHook;
Log : TLogInspector;
function TLogInspector.CallOrgWndProc(Message: TMessage): LRESULT;
begin
Result := CallWindowProc(OrgWndProc, WndHandle, Message.Msg, Message.wParam, Message.lParam);
end;
constructor TLogInspector.Create(AHandle: THandle);
begin
OrgWndProc := Pointer(GetWindowLongPtr(AHandle, GWL_WNDPROC));
ProcAddrInst := MakeObjectInstance(WndProc);
WndHandle := AHandle;
SetWindowLongPtr(WndHandle, GWL_WNDPROC, LONG_PTR(ProcAddrInst));
end;
procedure TLogInspector.WndProc(var Message: TMessage);
begin
//log the current message
TFile.AppendAllText('C:\Delphi\log.txt', 'WndProc '+IntToStr(Message.Msg)+sLineBreak);
//call the org WndProc
Message.Result := CallOrgWndProc(Message);
end;
function HookCallBack(nCode: Integer; _WPARAM: WPARAM; _LPARAM: LPARAM): LRESULT; stdcall;
var
lpClassName : array [0 .. 256] of Char;
begin
if nCode = HCBT_CREATEWND then
begin
GetClassName(_WPARAM, lpClassName, 256);
if lpClassName = 'TForm1' then
Log:= TLogInspector.Create(_WPARAM);
end;
Result := CallNextHookEx(MainHook, nCode, _WPARAM, _LPARAM);
end;
procedure InitLog; stdcall;
begin
MainHook := SetWindowsHookEx(WH_CBT, @HookCallBack, 0, GetCurrentThreadId);
end;
procedure DoneLog; stdcall;
begin
UnhookWindowsHookEx(MainHook);
end;
exports
InitLog, DoneLog;
begin
end.
应用
type
TForm1 = class(TForm)
Button1: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
procedure InitLog; stdcall; external 'LogDll.dll' name 'InitLog';
procedure DoneLog; stdcall; external 'LogDll.dll' name 'DoneLog';
implementation
{$R *.dfm}
initialization
InitLog;
finalization
DoneLog;
end.