利用 SetWindowsHookEx 安裝全域 Hook,攔截系統訊息流。兩種關鍵 Hook 類型:
function HookProc(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
Code:系統指示碼(如 HC_ACTION、HC_GETNEXT、HC_SKIP、HC_SYSMODALON/OFF)LParam:指向 EVENTMSG 結構,包含訊息詳細資訊
type
TForm1 = class(TForm)
Button1, Button2, Button3, Button4: TButton;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject); // 開始錄製
procedure Button2Click(Sender: TObject); // 停止錄製
procedure Button3Click(Sender: TObject); // 開始回放
private
public
end;
var
Form1: TForm1;
EventArr: array[0..1000] of EVENTMSG; // 事件緩衝區
EventLog, PlayLog: Integer; // 讀寫指標
hHook, hPlay: Integer; // Hook 控制代碼
recOK, canPlay: Integer; // 狀態旗標
bDelay: Bool; // 延遲旗標
function PlayProc(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
canPlay := 1;
Result := 0;
if iCode < 0 then
Result := CallNextHookEx(hPlay, iCode, wParam, lParam)
else if iCode = HC_SYSMODALON then
canPlay := 0
else if iCode = HC_SYSMODALOFF then
canPlay := 1
else if (canPlay = 1) and (iCode = HC_GETNEXT) then begin
if bDelay then begin
bDelay := False;
Result := 50; // 回放延遲 50ms
end;
PEVENTMSG(lParam)^ := EventArr[PlayLog]; // 回傳記錄的事件
end
else if (canPlay = 1) and (iCode = HC_SKIP) then begin
bDelay := True;
Inc(PlayLog);
end;
if PlayLog >= EventLog then
UnhookWindowsHookEx(hPlay); // 回放結束,移除 Hook
end;
function HookProc(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
recOK := 1;
Result := 0;
if iCode < 0 then
Result := CallNextHookEx(hHook, iCode, wParam, lParam)
else if iCode = HC_SYSMODALON then
recOK := 0
else if iCode = HC_SYSMODALOFF then
recOK := 1
else if (recOK > 0) and (iCode = HC_ACTION) then begin
EventArr[EventLog] := PEVENTMSG(lParam)^; // 存入事件
Inc(EventLog);
if EventLog >= 1000 then
UnhookWindowsHookEx(hHook); // 緩衝區滿,停止錄製
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '錄製';
Button2.Caption := '停止';
Button3.Caption := '回放';
Button4.Caption := '範例';
Button2.Enabled := False;
Button3.Enabled := False;
end;
procedure TForm1.Button1Click(Sender: TObject); // 開始錄製
begin
EventLog := 0;
hHook := SetWindowsHookEx(WH_JOURNALRECORD, @HookProc, HInstance, 0);
Button2.Enabled := True;
Button1.Enabled := False;
end;
procedure TForm1.Button2Click(Sender: TObject); // 停止錄製
begin
UnhookWindowsHookEx(hHook);
hHook := 0;
Button1.Enabled := True;
Button2.Enabled := False;
Button3.Enabled := True;
end;
procedure TForm1.Button3Click(Sender: TObject); // 開始回放
begin
PlayLog := 0;
hPlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, @PlayProc, HInstance, 0);
Button3.Enabled := False;
end;
HC_SYSMODALON/OFF 處理系統模態對話框干擾。HC_GETNEXT 要求提供下一個事件,HC_SKIP 通知跳過,配合 Result 回傳延遲毫秒數。WH_MOUSE_LL/WH_KEYBOARD_LL 低層級 Hook。透過 WH_JOURNALRECORD 與 WH_JOURNALPLAYBACK 雙 Hook 協作,可完整實現輸入事件的錄製與回放。理解 Hook 回呼流程、Code 指示碼含義與 EVENTMSG 結構,是掌握此技術的關鍵。