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

Delphi 鍵盤滑鼠動作錄製回放實作:WH_JOURNALRECORD 與 WH_JOURNALPLAYBACK Hook 機制完整教學

     編輯:Delphi

核心原理:系統全域 Hook

利用 SetWindowsHookEx 安裝全域 Hook,攔截系統訊息流。兩種關鍵 Hook 類型:

  • WH_JOURNALRECORD:記錄鍵盤/滑鼠輸入事件
  • WH_JOURNALPLAYBACK:回放已記錄的事件

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;                         // 延遲旗標

回放 Hook 函數


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;

錄製 Hook 函數


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;

關鍵技術細節

  • 緩衝區大小固定:範例限制 1000 筆事件,實際應用建議用動態陣列或串流。
  • 系統模態處理:HC_SYSMODALON/OFF 處理系統模態對話框干擾。
  • 回放時機控制:HC_GETNEXT 要求提供下一個事件,HC_SKIP 通知跳過,配合 Result 回傳延遲毫秒數。
  • 執行緒 ID 為 0:安裝全域 Hook(所有執行緒)。

注意事項與限制

  • Windows Vista+ 需管理員權限才能安裝全域 Hook。
  • 64 位元系統需 64 位元編譯的應用程式。
  • 現代 Windows 版本對 Journal Hook 有較嚴格限制,建議改用 WH_MOUSE_LL/WH_KEYBOARD_LL 低層級 Hook。
  • 緩衝區溢位會自動停止,需依需求擴充。

總結

透過 WH_JOURNALRECORD 與 WH_JOURNALPLAYBACK 雙 Hook 協作,可完整實現輸入事件的錄製與回放。理解 Hook 回呼流程、Code 指示碼含義與 EVENTMSG 結構,是掌握此技術的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved