Mega Code Archive

 
Categories / Delphi / VCL
 

Msgsimulator [component-delphi]

RemoteControl Project Note that this project also requires the TMsgSimulator component which can be found at the web page below. This component was downloaded from Ben's Delphi Page http://www.radix.net/~bziegler/Delphi -Ben Ziegler bziegler@radix.net ---------------------- main.dfm dosyası ---------------------- ÿ TMAINFORM 0 TPF0 TMainFormMainFormLeftTopkWidthºHeightàCaptionMsgSimulator Component Demo Font.CharsetDEFAULT_CHARSET Font.Color clWindowText Font.Heightõ Font.Name MS Sans Serif Font.Style PositionpoScreenCenter PixelsPerInch` TextHeight TLabelLabel1Left Top´Width²Height AlignalBottom AlignmenttaCenterCaptionJThis program demonstrates the capabilities of the TMsgSimulator component. TButton SimClickButLeftTopWidthÑ HeightCaption&Simulate Button ClickTabOrder OnClickSimClickButClick TButtonBeepButLeftTop8WidthKHeightCaption&BeepTabOrderOnClick BeepButClick TButton SimKeyButLeftToppWidthÑ HeightCaptionSimulate &KeystrokesTabOrderOnClickSimKeyButClick TEditEdit1LeftTop˜ Width HeightTabOrderTextEdit1 TButtonButton1LeftTopÈ WidthÑ HeightCaptionType &Text into notepadTabOrderOnClick Button1Click TButton RecordButLeftTopğ WidthKHeightCaption&RecordTabOrderOnClickRecordButClick TButtonStopButLeftpTopğ WidthKHeightCaptionSto&pEnabledTabOrderOnClick StopButClick TButtonPlayButLeftĞ Topğ WidthKHeightCaption&PlayTabOrderOnClick PlayButClick TMemoMemo1LeftTopWidth¡Height‘ Font.Charset ANSI_CHARSET Font.Color clWindowText Font.Heightõ Font.Name Courier New Font.Style ParentFont ScrollBarsssBothTabOrderWordWrap TMsgSimulator MsgSimulator1Messages OnStopRecordMsgSimulator1StopRecordLeftÀ Top0 ------------------------------------ main.dfm bitiş ----------------------------------- ---------------------- main.pas dosyası ---------------------- unit Main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, MsgSimulator, ShellAPI; type TMainForm = class(TForm) Label1: TLabel; SimClickBut: TButton; BeepBut: TButton; MsgSimulator1: TMsgSimulator; SimKeyBut: TButton; Edit1: TEdit; Button1: TButton; RecordBut: TButton; StopBut: TButton; PlayBut: TButton; Memo1: TMemo; procedure BeepButClick(Sender: TObject); procedure SimClickButClick(Sender: TObject); procedure SimKeyButClick(Sender: TObject); procedure Button1Click(Sender: TObject); procedure RecordButClick(Sender: TObject); procedure PlayButClick(Sender: TObject); procedure StopButClick(Sender: TObject); procedure MsgSimulator1StopRecord(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.DFM} procedure TMainForm.BeepButClick(Sender: TObject); begin Beep; end; procedure TMainForm.SimClickButClick(Sender: TObject); begin with MsgSimulator1 do begin Messages.Clear; Add_Window_Click(BeepBut.Handle, 5, 5); Play; end; SimClickBut.SetFocus; end; procedure TMainForm.SimKeyButClick(Sender: TObject); begin with MsgSimulator1 do begin Messages.Clear; Add_ASCII_Keys('This is a Test!'); Edit1.SetFocus; Play; end; SimKeyBut.SetFocus; end; procedure TMainForm.Button1Click(Sender: TObject); var StartInfo : TStartupInfo; ProcInfo : TProcessInformation; begin GetStartupInfo(StartInfo); Win32Check(CreateProcess(nil, 'notepad.exe', nil, nil, True, 0, nil, nil, StartInfo, ProcInfo)); WaitForInputIdle(ProcInfo.hProcess, INFINITE); with MsgSimulator1 do begin Messages.Clear; Add_ASCII_Keys('This is a Test!'#13); Add_ASCII_Keys('Next I will simulate an "F5" keypress:'#13); Add_VirtualKey(0, VK_F5, 1, mmKeyDown); Add_VirtualKey(0, VK_F5, 1, mmKeyUp); Play; end; end; procedure TMainForm.RecordButClick(Sender: TObject); begin MsgSimulator1.Record_Input; StopBut.Enabled := True; end; procedure TMainForm.PlayButClick(Sender: TObject); begin MsgSimulator1.Play; end; procedure TMainForm.StopButClick(Sender: TObject); begin MsgSimulator1.Stop_Record; end; procedure TMainForm.MsgSimulator1StopRecord(Sender: TObject); var i : integer; mi : TMessageItem; s : string; begin StopBut.Enabled := False; for i := 0 to MsgSimulator1.Messages.Count-1 do begin mi := MsgSimulator1.Messages[i]; s := Format('Msg: %3d X: %4d Y: %4d Key: %4.4x Delay: %4d', [integer(mi.Msg), mi.PosX, mi.PosY, mi.VkKey, mi.Delay]); Memo1.Lines.Add(s); end; end; end. ------------------------------------ main.pas bitiş ----------------------------------- ---------------------- msgsimdemo.dpr dosyası ---------------------- program MsgSimDemo; uses Forms, Main in 'Main.pas' {MainForm}; {$R *.RES} begin Application.Initialize; Application.Title := 'MsgSimulator Component Demo'; Application.CreateForm(TMainForm, MainForm); Application.Run; end. ------------------------------------ msgsimdemo.dpr bitiş ----------------------------------- ---------------------- msgsimdemo.res dosyası ---------------------- ÿÿ ÿÿ è ÿÿ ÿÿ   ( @    € € €€ € € € €€ €€€ ÀÀÀ ÿ ÿ ÿÿ ÿ ÿ ÿ ÿÿ ÿÿÿ wx ÌÌÌÌ ‡€ ÌÌÌÌÌÌ ‡øx ÌLÌLÌLÌ ø‡€ÌÌÌÌÌÌÌÀ ‡øx LLLLLLL ø‡€ÌÌÌÌÌÌÌÀ ‡øx LLLLLLL Çø‡€ÌÌÌÌÌÌÌ L‡øx LLLLLL@ ÄÇø‡€ÄÄÄÄÄÄÀ LL‡÷w LLLLLL ÄÄÇøxwp ÄÄÄÄÄ LLL‡‡ HLL ÄÄÄÇ÷xpx €„„Ä LLLLxw‡yˆHL ÄÄÄć‡p‡¹™„Ä LLLLGw÷{û¹˜L ÄÄÄćxx÷¿¹™˜Ä DDDDHw{ûû¹™ğ ÄÄÄÄ„x÷»¿¿›™ğ DDDHxy¿»»™™Ÿ ÄÄÄ„÷™»ù›¹™˜ğ DDDHH™›¹™›™Ÿ DDD„ù™›»™™˜ğ DDDHH™™™¹™Ÿ DDD„øù™›™˜ğ DD@O›™ ø›™ğ ™Ÿ ù™ğ  Ãÿÿÿğÿ€Àÿ€ ÿ€ À ?à ğ ğ ğ à à à à à à à à à ğ ğ ø ø ü ş ÿ ÿÀ ÿğHÿÿüÿÿşÿÿüÿÿş? 0 ÿÿ M A I N I C O N     r  è  ------------------------------------ msgsimdemo.res bitiş ----------------------------------- ---------------------- msgsimdemo.dcr dosyası ---------------------- ÿÿ ÿÿ ˆ 8 ÿÿ T M S G S I M U L A T O R   (      € € €€ € € € €€ €€€ ÀÀÀ ÿ ÿ ÿÿ ÿ ÿ ÿ ÿÿ ÿÿÿ ˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆİ؈ˆˆ€ÿˆˆˆİ݈€ˆ€ÿˆˆˆİ݈€ğˆˆˆˆİ݈€ğğˆˆˆˆˆİ؈€ÿÿˆˆˆˆˆˆˆˆ€ÿÿ ˆˆˆˆˆfh€ÿÿÿˆˆˆˆ†ff€ÿÿğˆˆˆ»¸†ff€ÿÿˆˆ‹»»†ff€ÿğˆˆˆ‹»»ˆfh€ÿˆˆˆ‹»»ˆˆˆ€ğˆ™˜ˆˆ»¸ˆˆˆ€‰™™ˆˆˆˆˆˆˆˆˆ‰™™ˆˆˆˆˆŒÌˆˆ‰™™ˆˆˆˆˆÌÌȈˆ™˜ˆˆˆˆˆÌÌȈˆˆˆˆŠªˆˆÌÌȈŽîˆˆªª¨ˆŒÌˆˆîî航ª¨ˆˆˆˆˆîî航ª¨ˆˆˆˆˆîî舊ªˆˆˆˆˆˆŽîˆˆˆˆˆˆˆˆˆˆˆˆˆ ---------------------------- msgsimdemo.dcr bitiş ----------------------------------- ---------------------- msgsimdemo.pas dosyası ---------------------- unit MsgSimulator; { June 23, 1998 by Ben Ziegler 6/30/98 - Added a Record Macro function } interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TWMMessage = (mmMouseDown, mmMouseUp, mmMouseMove, mmKeyDown, mmKeyUp); TMessageItem = class(TCollectionItem) protected em : TEventMsg; // Structure required by JournalPlayback Proc FMsg : TWMMessage; FDelay : DWORD; // Delay in msec before next message is played FX : integer; // This means nothing for keystrokes FY : integer; // This means nothing for keystrokes FKey : integer; // This means nothing for mouse clicks FHWND : integer; // Window Handle (not used for keystrokes) FButton : TMouseButton; // This means nothing for keystrokes procedure Fill_EM_From_Props; procedure Fill_Props_From_EM; public constructor Create(Collection: TCollection); override; property HWND : integer read FHWND write FHWND; // No need to save it - it will be different after each run published property Msg : TWMMessage read FMsg write FMsg; property PosX : integer read FX write FX; property PosY : integer read FY write FY; property VkKey : integer read FKey write FKey; property Delay : DWORD read FDelay write FDelay; property Button : TMouseButton read FButton write FButton; end; TMsgSimulator = class; TMessageCollection = class(TCollection) private FOwner : TMsgSimulator; function GetItem(Index: Integer): TMessageItem; procedure SetItem(Index: Integer; Value: TMessageItem); protected function GetOwner: TPersistent; override; procedure Update(Item: TCollectionItem); override; public constructor Create(AOwner: TMsgSimulator); function Add: TMessageItem; property Owner: TMsgSimulator read FOwner; property Items[Index: Integer]: TMessageItem read GetItem write SetItem; default; end; TMsgSimulator = class(TComponent) protected FRunning : boolean; // Simulation is currently running play_hk : THandle; // JournalPlayback Hook handle rec_hk : THandle; // RecordPlayback Hook handle PlayDone : boolean; // Flag to signal that all messages have been simulated AbortSim : boolean; // Flag to signal aborting the playback of messages StartTime : DWORD; // Time simulation started (msec) StopTime : DWORD; // Time simulation stoped (msec) FDelay : integer; // Default delay between messages FMsgList : TMessageCollection; // Messages to playback FTopWin : string; FindText : string; FindHandle : THandle; StopRec : integer; FRecording : boolean; FOnStopRec : TNotifyEvent; function GetElapTime: integer; procedure SetMsgList(MsgList: TMessageCollection); function Add_Raw_Message(Msg: TWMMessage; x, y, VkKey, Delay, HWND: integer; Button: TMouseButton): TMessageItem; procedure Add_Shift(hwnd: THandle; Shift: TShiftState; UpDown: TWMMessage; Delay: integer); procedure SimClientToScreen(hwnd: THandle; var x, y: integer); procedure FixUp_Playback_Delays; procedure FixUp_Record_Delays; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; // Low-level Message Creation Functions procedure Add_ClickEx(hwnd: THandle; Button: TMouseButton; Shift: TShiftState; x, y, Delay: integer); procedure Add_DragEx(hwnd: THandle; Button: TMouseButton; Shift: TShiftState; StartX, StartY, StopX, StopY, NumMoves, Delay: integer); procedure Add_VirtualKey(hwnd: THandle; VkKey, Delay: integer; UpDown: TWMMessage); // High-level Message Creation Functions procedure Add_Window_Click(hwnd: THandle; x, y: integer); procedure Add_Window_Drag(hwnd: THandle; StartX, StartY, StopX, StopY: integer); procedure Add_Screen_Click(x, y: integer); procedure Add_Screen_Drag(StartX, StartY, StopX, StopY: integer); procedure Add_ASCII_Keys(const Keystrokes: string); public // Playback & Cancel Functions procedure Play; // Plays messages, then returns procedure Play_Async; // Returns immediately procedure Abort; procedure Record_Input; procedure Stop_Record; property Running: boolean read FRunning; property Recording: boolean read FRecording; property ElapTime: integer read GetElapTime; // Elapsed running time in msec // Helper Functions procedure FocusWin(hwnd: THandle); function FindTopLevelWin(const FindText: string): THandle; published property Messages: TMessageCollection read FMsgList write SetMsgList; property DefaultDelay: integer read FDelay write FDelay default 50; property OnStopRecord: TNotifyEvent read FOnStopRec write FOnStopRec; end; procedure Register; implementation var CurSim : TMsgSimulator; // Only one TMsgSimulator can play at a time Cur : integer; // Current Message to play in the MsgList NumCur : integer; // Number of times current message has been played procedure Register; begin RegisterComponents('Samples', [TMsgSimulator]); end; // ********************************************************************* // TMessageItem constructor TMessageItem.Create(Collection: TCollection); begin inherited; Delay := TMessageCollection(Collection).Owner.DefaultDelay; end; procedure TMessageItem.Fill_EM_From_Props; begin em.hwnd := hwnd; if (Msg = mmMouseDown) and (Button = mbLeft) then em.message := WM_LBUTTONDOWN; if (Msg = mmMouseUp) and (Button = mbLeft) then em.message := WM_LBUTTONUP; if (Msg = mmMouseDown) and (Button = mbRight) then em.message := WM_RBUTTONDOWN; if (Msg = mmMouseUp) and (Button = mbRight) then em.message := WM_RBUTTONUP; if (Msg = mmMouseDown) and (Button = mbMiddle) then em.message := WM_MBUTTONDOWN; if (Msg = mmMouseUp) and (Button = mbMiddle) then em.message := WM_MBUTTONUP; case Msg of mmMouseMove : em.message := WM_MOUSEMOVE; mmKeyDown : em.message := WM_KEYDOWN; mmKeyUp : em.message := WM_KEYUP; end; if (Msg = mmKeyDown) or (Msg = mmKeyUp) then begin // Keystroke Message em.paramL := VkKey; em.paramH := MapVirtualKey(VkKey, 0); end else begin // Mouse Message em.paramL := PosX; em.paramH := PosY; end; end; procedure TMessageItem.Fill_Props_From_EM; begin hwnd := em.hwnd; case em.message of WM_LBUTTONDOWN : begin Msg := mmMouseDown; Button := mbLeft; end; WM_LBUTTONUP : begin Msg := mmMouseUp; Button := mbLeft; end; WM_RBUTTONDOWN : begin Msg := mmMouseDown; Button := mbRight; end; WM_RBUTTONUP : begin Msg := mmMouseUp; Button := mbRight; end; WM_MBUTTONDOWN : begin Msg := mmMouseDown; Button := mbMiddle; end; WM_MBUTTONUP : begin Msg := mmMouseUp; Button := mbMiddle; end; WM_MOUSEMOVE : Msg := mmMouseMove; WM_KEYDOWN : Msg := mmKeyDown; WM_KEYUP : Msg := mmKeyUp; end; if (Msg = mmKeyDown) or (Msg = mmKeyUp) then begin // Keystroke Message VkKey := em.paramL; end else begin // Mouse Message PosX := em.paramL; PosY := em.paramH; end; end; // ********************************************************************* // TMessageCollection constructor TMessageCollection.Create(AOwner: TMsgSimulator); begin inherited Create(TMessageItem); FOwner := AOwner; end; function TMessageCollection.Add: TMessageItem; begin Result := TMessageItem(inherited Add); end; function TMessageCollection.GetItem(Index: Integer): TMessageItem; begin Result := TMessageItem(inherited GetItem(Index)); end; function TMessageCollection.GetOwner: TPersistent; begin Result := FOwner; end; procedure TMessageCollection.SetItem(Index: Integer; Value: TMessageItem); begin inherited SetItem(Index, Value); end; procedure TMessageCollection.Update(Item: TCollectionItem); begin Assert(not FOwner.Running); end; // ********************************************************************* // TMsgSimulator constructor TMsgSimulator.Create(AOwner: TComponent); begin inherited; FDelay := 50; FMsgList := TMessageCollection.Create(Self); end; destructor TMsgSimulator.Destroy; begin if Running then Abort; FMsgList.Free; FMsgList := nil; inherited; end; procedure TMsgSimulator.SetMsgList(MsgList: TMessageCollection); begin FMsgList.Assign(MsgList); end; function TMsgSimulator.Add_Raw_Message(Msg: TWMMessage; x, y, VkKey, Delay, HWND: integer; Button: TMouseButton): TMessageItem; begin Result := Messages.Add; Result.Msg := Msg; Result.PosX := x; Result.PosY := y; Result.VkKey := VkKey; Result.Delay := Delay; Result.HWND := HWND; Result.Button := Button; end; procedure TMsgSimulator.Add_Shift(hwnd: THandle; Shift: TShiftState; UpDown: TWMMessage; Delay: integer); begin // NOTE: Keystrokes do not require an hwnd, so use 0 if Shift = [] then exit; if ssShift in Shift then Add_Raw_Message(UpDown, 0, 0, VK_SHIFT, Delay, 0, mbLeft); if ssCtrl in Shift then Add_Raw_Message(UpDown, 0, 0, VK_CONTROL, Delay, 0, mbLeft); if ssAlt in Shift then Add_Raw_Message(UpDown, 0, 0, VK_MENU, Delay, 0, mbLeft); end; // x, y are in Screen coordinates procedure TMsgSimulator.Add_ClickEx(hwnd: THandle; Button: TMouseButton; Shift: TShiftState; x, y, Delay: integer); begin Add_Shift(hwnd, Shift, mmKeyDown, Delay); Add_Raw_Message(mmMouseDown, x, y, 0, Delay, hwnd, Button); Add_Raw_Message(mmMouseUp, x, y, 0, Delay, hwnd, Button); Add_Raw_Message(mmMouseMove, x, y, 0, Delay, hwnd, Button); Add_Shift(hwnd, Shift, mmKeyUp, Delay); end; // x, y are in Screen coordinates procedure TMsgSimulator.Add_DragEx(hwnd: THandle; Button: TMouseButton; Shift: TShiftState; StartX, StartY, StopX, StopY, NumMoves, Delay: integer); var i, x, y : integer; begin Add_Shift(hwnd, Shift, mmKeyDown, Delay); Add_Raw_Message(mmMouseDown, StartX, StartY, 0, Delay, hwnd, Button); for i := 0 to NumMoves do begin x := (StopX - StartX) * i div NumMoves + StartX; y := (StopY - StartY) * i div NumMoves + StartY; Add_Raw_Message(mmMouseMove, x, y, 0, Delay, hwnd, Button); end; Add_Raw_Message(mmMouseUp, StopX, StopY, 0, Delay, hwnd, Button); Add_Shift(hwnd, Shift, mmKeyUp, Delay); end; procedure TMsgSimulator.Add_VirtualKey(hwnd: THandle; VkKey, Delay: integer; UpDown: TWMMessage); begin Add_Raw_Message(upDown, 0, 0, vkKey, Delay, hwnd, mbLeft); end; procedure TMsgSimulator.SimClientToScreen(hwnd: THandle; var x, y: integer); var p : TPoint; begin if hwnd = 0 then exit; p := Point(x, y); Windows.ClientToScreen(hwnd, p); x := p.x; y := p.y; end; // x, y are in the Window's coordinates procedure TMsgSimulator.Add_Window_Click(hwnd: THandle; x, y: integer); begin SimClientToScreen(hwnd, x, y); Add_ClickEx(hwnd, mbLeft, [], x, y, DefaultDelay); end; // StartXY & StopXY are in the Window's coordinates procedure TMsgSimulator.Add_Window_Drag(hwnd: THandle; StartX, StartY, StopX, StopY: integer); begin SimClientToScreen(hwnd, StartX, StartY); SimClientToScreen(hwnd, StopX, StopY); Add_DragEx(hwnd, mbLeft, [], StartX, StartY, StopX, StopY, 10, DefaultDelay); end; // x, y are in Screen coordinates procedure TMsgSimulator.Add_Screen_Click(x, y: integer); var hwnd : THandle; begin hwnd := Windows.WindowFromPoint(Point(x, y)); Add_ClickEx(hwnd, mbLeft, [], x, y, DefaultDelay); end; // x, y are in Screen coordinates procedure TMsgSimulator.Add_Screen_Drag(StartX, StartY, StopX, StopY: integer); var hwnd : THandle; begin hwnd := Windows.WindowFromPoint(Point(StartX, StartY)); Add_DragEx(hwnd, mbLeft, [], StartX, StartY, StopX, StopY, 10, DefaultDelay); end; procedure TMsgSimulator.Add_ASCII_Keys(const Keystrokes: string); var i : integer; c : byte; Shift : boolean; begin for i := 1 to Length(Keystrokes) do begin c := VkKeyScan(Keystrokes[i]) and 255; Shift := (VkKeyScan(Keystrokes[i]) and 256) <> 0; if Shift then Add_Raw_Message(mmKeyDown, 0, 0, VK_SHIFT, 1 {DefaultDelay}, 0, mbLeft); Add_Raw_Message(mmKeyDown, 0, 0, c, DefaultDelay, 0, mbLeft); Add_Raw_Message(mmKeyUp, 0, 0, c, 1 {DefaultDelay}, 0, mbLeft); if Shift then Add_Raw_Message(mmKeyUp, 0, 0, VK_SHIFT, 1 {DefaultDelay}, 0, mbLeft); end; end; procedure TMsgSimulator.Play; begin Play_Async; Assert(Application <> nil, 'TMsgSimulator.Play: Application = nil'); while (not Application.Terminated) and (not AbortSim) and (not PlayDone) do begin Application.ProcessMessages; Sleep(1); end; end; procedure UnHook; begin Win32Check(UnhookWindowsHookEx(CurSim.play_hk)); CurSim.play_hk := 0; CurSim.PlayDone := True; CurSim.StopTime := GetTickCount; CurSim.FRunning := False; CurSim := nil; end; function JournalPlaybackProc(code: integer; wp: WParam; lp: LPARAM): LResult; stdcall; var pe : PEventMsg; begin Assert(CurSim <> nil, 'CurSim = nil!'); Assert(CurSim.PlayDone = False, 'Still Playing?'); Result := CallNextHookEx(CurSim.play_hk, code, wp, lp); if code < 0 then exit; if CurSim.AbortSim then begin UnHook; exit; end; if code = HC_GETNEXT then begin pe := @CurSim.Messages[Cur].em; PEventMsg(lp)^ := pe^; Result := 0; if (NumCur = 0) and (Cur > 0) then begin Result := CurSim.Messages[Cur].em.time - CurSim.Messages[Cur-1].em.time; end; NumCur := NumCur + 1; exit; end; if code = HC_SKIP then begin Cur := Cur + 1; NumCur := 0; if Cur = CurSim.Messages.Count then begin UnHook; end; exit; end; end; procedure TMsgSimulator.FixUp_Playback_Delays; var i : integer; begin for i := 0 to Messages.Count-1 do begin Messages[i].Fill_EM_From_Props; if i = 0 then Messages[i].em.time := 0 else Messages[i].em.time := Messages[i-1].em.time + Messages[i].Delay; // TODO: Fix up HWNDs? -bpz end; end; // This function returns immediately procedure TMsgSimulator.Play_Async; begin StartTime := GetTickCount; StopTime := StartTime; if Messages.Count = 0 then exit; FRunning := True; AbortSim := False; PlayDone := False; Assert(CurSim = nil, 'A TMsgSimulator is already playing or recording!'); CurSim := Self; FixUp_Playback_Delays; // Set up the JournalPlayback Hook Cur := 0; NumCur := 0; play_hk := SetWindowsHookEx(WH_JOURNALPLAYBACK, JournalPlaybackProc, HInstance, 0); end; function TMsgSimulator.GetElapTime: integer; begin if Running then Result := GetTickCount - StartTime else Result := StopTime - StartTime; end; procedure TMsgSimulator.Abort; begin Assert(Running, 'Must be running to Abort!'); AbortSim := True; end; function JournalRecordProc(code: integer; wp: WParam; lp: LPARAM): LResult; stdcall; var pe : PEventMsg; mi : TMessageItem; begin Result := 0; case code of HC_ACTION : if (CurSim.StopRec = 0) then begin pe := PEventMsg(lp); if (pe.message = WM_KEYDOWN) and ((pe.paramL and 255) = VK_CANCEL) then begin CurSim.Stop_Record; exit; end; mi := CurSim.Messages.Add; mi.em := pe^; mi.Fill_Props_From_EM; end; HC_SYSMODALON : Inc(CurSim.StopRec); HC_SYSMODALOFF : Dec(CurSim.StopRec); end; end; procedure TMsgSimulator.Record_Input; begin Assert(CurSim = nil, 'A TMsgSimulator is already playing or recording!'); CurSim := Self; StopRec := 0; Messages.Clear; FRecording := True; rec_hk := SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProc, HInstance, 0); end; procedure TMsgSimulator.FixUp_Record_Delays; var i : integer; begin for i := 0 to Messages.Count-1 do begin if i = Messages.Count-1 then Messages[i].Delay := 0 else Messages[i].Delay := Messages[i+1].em.time - Messages[i].em.time; end; end; procedure TMsgSimulator.Stop_Record; begin if Recording then begin Win32Check(UnhookWindowsHookEx(CurSim.rec_hk)); rec_hk := 0; CurSim := nil; FRecording := False; FixUp_Record_Delays; if Assigned(OnStopRecord) then OnStopRecord(Self); // This is useful when the user hits CTRL-BREAK to stop recording rather than pressing a "Stop" button end; end; procedure TMsgSimulator.FocusWin(hwnd: THandle); var tmp : THandle; begin // Get the top-level window tmp := hwnd; while GetParent(tmp)<>0 do tmp := GetParent(tmp); SetForegroundWindow(tmp); Windows.SetFocus(hwnd); end; function EnumWindowsProc(hwnd: THandle; lp: LParam): boolean; stdcall; var buf : array[0..MAX_PATH] of char; ms : TMsgSimulator; begin Result := True; ms := TMsgSimulator(lp); Assert(ms<>nil); GetWindowText(hwnd, buf, sizeof(buf)); if Pos(ms.FindText, buf)<>0 then ms.FindHandle := hwnd; end; function TMsgSimulator.FindTopLevelWin(const FindText: string): THandle; begin Self.FindText := FindText; FindHandle := DWORD(-1); EnumWindows(@EnumWindowsProc, LParam(Self)); Result := FindHandle; end; initialization CurSim := nil; end. ---------------------------- msgsimdemo.pas bitiş -----------------------------------