VCL 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ş -----------------------------------