//This unit requires the
WINLDOWLIST unit in order for the FindAWindow // function to compile. That function is NOT necessary to use this
unit; if // you don't have the WINDOWLIST
unit (which is freeware) remove the declaration // above, comment out the FindAWindow function, and this unit
should compile.
// *********************************** // SimulateKeyStroke // // Simulates hitting a key,
which is sent to active // window. // //************************************
procedure SimulateKeystroke(Key : byte; extra : DWORD); begin keybd_event(Key,extra,0,0);
keybd_event(Key,
extra,KEYEVENTF_KEYUP,0); end;
// *********************************** // SimulateKeyDown // // Simulates holding down a
key, such as shift or ALT // // //************************************
procedure SimulateKeyDown(Key
: byte); begin keybd_event(Key, 0, 0, 0);
end;
// *********************************** // SimulateKeyUp // // Simulates releasing a
key, such as shift or ALT // // //************************************ procedure SimulateKeyUp(Key
: byte); begin keybd_event(Key, 0, KEYEVENTF_KEYUP, 0);
end;
// *********************************** // SendKeys // // Sends a string to the
window specified // by TargetHWND. Uses
SetForegroundWindow // to make sure keys go
to the right place. // //************************************ procedure SendKeys(s : string; targethwnd : hwnd); var i : integer;
flag : bool; w : word;
d1,d2 : integer; //
for delay loop begin SetForegroundWindow(targetHwnd);
// GET TO THE RIGHT WINDOW {Get the state of the caps lock
key} flag := not GetKeyState(VK_CAPITAL) and 1 = 0;
{If the caps lock key is
on then turn it off} if flag then SimulateKeystroke(VK_CAPITAL, 0);
for i := 1
to Length(s) do begin for d1 := 1 to 1000 do// Delay a tiny bit to allow
keys to be accepted. for d2 := 1 to 250 do// THis needs tested on a SLOW
PC! begin end;
SetForegroundWindow(targetHwnd);
// REQUIRED! Verify target window w := VkKeyScan(s[i]);
{If
there is not an error in the key translation} if ((HiByte(w)
‹› $FF) and (LoByte(w) ‹› $FF)) then begin {If the key requires the shift key down - hold it down} if HiByte(w) and 1 = 1
then SimulateKeyDown(VK_SHIFT);
{Send the VK_KEY} SimulateKeystroke(LoByte(w), 0);
{If the key required the shift key down - release it} if HiByte(w) and 1 = 1
then SimulateKeyUp(VK_SHIFT);
end;
end; {if the caps lock key was on at start, turn it back on} if flag
then SimulateKeystroke(VK_CAPITAL, 0);
end;
function FindInBraces(s : string; StartAt : integer): string; // Given a string and a starting
point, finds the next set of // braces and
returns the characters inside var
Beginpos, Endpos : integer;
bbrace, ebrace : string; begin bbrace := BEGINBRACE;
ebrace := ENDBRACE;
Beginpos := forwardpos(bbrace,s,StartAt); Endpos := forwardpos(ebrace,s,beginpos+1);
Result := copy(s,beginpos+1,endpos-beginpos-1); end;
// Returns the location of the next BEGINBRACE character which
denotes // the beginning of a complete set.
In order to be counted, the set must // be
terminated with an ENDBRACE character. If no BEGINBRACE character is // found to denote the beginning of a set after the
specified location, // function returns
0. function FindNextSetBegin(s : string; StartAt : integer): integer; var x,bbrace,setcount : integer; InSet,done : boolean; begin setcount := 0;
bbrace := 0;
InSet := false;
done := false; x
:= 1; while (x ‹= length(s))and (not done) do begin if
(s[x]
= BEGINBRACE) and (not Inset) then begin InSet := true;
bbrace := x;
// we're PROBABLY beginning a set end;
if
(s[x]
= ENDBRACE) and (InSet) then begin Inset := false;
inc(setCount);
// we just finished a set so count it. if bbrace ›= StartAt then Done := true;
end;
inc(x);
end; if
(done) and (setcount › 0) then Result := bbrace
else Result := 0;
end;
// Returns the next END BRACE location equal to or after
the // specified position in the string.
Since Brace sets are counted // from the VERY
BEGINNING of the string, this MAY NOT return the // next occurence of the end brace character. // Example: FindNextSetEnd('1}3}5{}',1) would return 7, because
the // set beginning is at position 6.
Returns 0 if no Set End Brace is // found
after the given location. function FindNextSetEnd(s
: string; StartAt : integer): integer;
var x,bbrace,ebrace,setcount : integer;
InSet,done : boolean; begin setcount := 0; bbrace := 0;
ebrace := 0;
InSet := false;
done := false; x
:= 1; while (x ‹= length(s))and (not done) do begin if
(s[x]
= BEGINBRACE) and (not Inset) then begin InSet := true;
bbrace := x;
// we're PROBABLY beginning a set end;
if
(s[x]
= ENDBRACE) and (InSet) then begin Inset := false;
ebrace := x;
inc(setCount);
// we just finished a set so count it. if bbrace ›= StartAt then Done := true;
end;
inc(x);
end; if
(done) and (setcount › 0) then Result := ebrace
else Result := 0;
end;
// Returns the number of full sets of braces in a given
string // Note - doesn't count braces that
aren't making up a set. // So {{{} counts as
one, and {{}} counts as one. {}{} would be 2. // No "set inside a set" functionality is taken into
account. function
CountBraceSets(s : string): integer; var x,setcount : integer;
InSet : boolean; begin setcount := 0;
InSet := false; x
:= 1; while (x ‹= length(s)) do begin if
(s[x]
= BEGINBRACE) and (not Inset) then begin InSet := true;
// we're PROBABLY beginning a set end;
if
(s[x]
= ENDBRACE) and (InSet) then begin Inset := false;
inc(setCount);
// we just finished a set so count it. end;
inc(x);
end; Result := setcount; end;
function
GetBraceValue(s : string; SetNum : integer) : string; // Returns the text in between a set
of braces. SetNum denotes the // set to
return. var count,sloc : integer; begin if (setnum ‹=
countbracesets(s)) and (setnum › 0) then begin count := 1; sloc := FindNextSetBegin(s,1);
while count
‹= (setnum-1) do begin sloc := FindNextSetBegin(s,sloc);
inc(count);
sloc := FindNextSetEnd(s,sloc); end;
result := findinbraces(s,sloc); end else result
:= ''; end;
// For special codes which can be translated directly into one
character // bytes, we use this function to
cconvert them (ie {ENTER}=chr(13) etc) //
This gets them out of the way before more involved code-handling // routines attempt to sort out the remaining brace
codes. This function // should not need to be
used by any user function; it's a helper function // for other functions in this unit. Function ReplaceSpecialKeys(keystr : string) : string; // Replaces certain brace characters
with their ascii equivalents var
Flags: TReplaceFlags; begin Flags := [rfReplaceAll,rfIgnoreCase]; keystr := StringReplace(keystr, '{ENTER}', chr(13), Flags);
keystr := StringReplace(keystr, '{TAB}',
chr(9), Flags); keystr := StringReplace(keystr, '{ESC}',
chr(27), Flags); keystr := StringReplace(keystr, '{ESCAPE}', chr(27), Flags); result := keystr; end;
//***************************************************************** // SendKeysEx - An Extended Sendkeys function which
converts special // text combinations into
keystrokes. Example: {ENTER} is turned into // chr(13), {TAB} = chr(9), etc. Also, {ALT-F} sends ALT and F,
and // ALTDOWN holds down the ALT key, ALTUP
lets it up, etc. See the code // for all the
special codes. This requires the SendKey function, but // can be used in place of the SendKeys function. The Sendkeys
function // doesn't handle special codes like
SendKeysEx does. //********************************************************************* Procedure SendKeysEx( s : string; targethwnd : hwnd);
// Replaces special keys, and handles ALT and CTRL
keys var bb,eb : integer; tempstr,braceval,workstr : string; begin SetForegroundWindow(targetHwnd); // Make sure
the correct window recieves focus workstr := ReplaceSpecialKeys(s); // Turn {ENTER}, {TAB}, etc into chars first if CountBraceSets(workstr) ›
0 then// we have braces begin bb := FindNextSetBegin(workstr,1); // get the location of first brace set repeat //bb :=
FindNextSetBegin(workstr,currentpos); // get the location of first brace
set eb
:= FindNextSetEnd(workstr,bb); // set the
brace end too if bb › 1 then//send keys before current set of braces begin tempstr
:= copy(workstr,1,bb-1); // copy data sendkeys(tempstr,targethwnd); // send
it delete(workstr,1,bb-1); // wipe out everything we just sent // reset bb and eb since we changed string size bb
:= FindNextSetBegin(workstr,1);
//eb := FindNextSetEnd(workstr,bb); //currentpos := bb; // brace end now becomes beginning of
string end else begin braceval
:= getbracevalue(workstr,1); // return what's in set of braces SendInBraces(braceval,targethwnd); // handle
it delete(workstr,1,eb); // wipe brace set from
workstring bb
:= FindNextSetBegin(workstr,1); // get the location of next brace set end;
//showmessage(inttostr(bb)); until bb
= 0; // no more braces if
length(workstr) ‹› 0 then// more keys to send after
last brace set, so send 'em sendkeys(workstr,targethwnd); end else begin// no braces, just send the
string! sendkeys(workstr, targethwnd); end; end;
/// Simulates a keystroke by pressing then releasing virtual
key procedure keystroke( key : byte); begin simulatekeydown(key);
simulatekeyup(key); end;
// Procedure used by SendKeysEx. Should not need to be called by
any user // function. procedure sendinbraces(s : string; targethwnd : hwnd); var dashpos : integer;
predash,postdash : string; begin s
:= trim(s);
dashpos := pos('-',s); if dashpos
› 0 then begin predash := uppercase(copy(s,1,dashpos-1));
postdash := copy(s,dashpos+1,length(s));
if predash = 'ALT' then begin SetForegroundWindow(targetHwnd);
simulatekeydown(vk_Menu);
sendkeys(postdash,targethwnd);
simulatekeyup(vk_Menu);
end;
if predash = 'CTRL' then begin SetForegroundWindow(targetHwnd);
simulatekeydown(vk_Control);
sendkeys(postdash,targethwnd);
simulatekeyup(vk_Control);
end;
if predash = 'SHIFT' then begin SetForegroundWindow(targetHwnd);
simulatekeydown(vk_shift);
sendkeys(postdash,targethwnd);
simulatekeyup(vk_shift);
end;
end else begin// simulate single keypresses s:= uppercase(s);
SetForegroundWindow(targetHwnd);
if
s = 'ALTDOWN' then simulatekeydown(vk_Menu);
if
s = 'ALTUP' then simulatekeyup(vk_menu);
if
s = 'CTRLDOWN' then simulatekeydown(vk_control);
if
s = 'CTRLUP' then simulatekeyup(vk_control);
if
s = 'SHIFTDOWN' then simulatekeydown(vk_shift);
if
s = 'SHIFTUP' then simulatekeyup(vk_shift);
if
s = 'F1' then keystroke(vk_F1);
if
s = 'F2' then keystroke(vk_F2);
if
s = 'F3' then keystroke(vk_F3);
if
s = 'F4' then keystroke(vk_F4);
if
s = 'F5' then keystroke(vk_F5);
if
s = 'F6' then keystroke(vk_F6);
if
s = 'F7' then keystroke(vk_F7);
if
s = 'F8' then keystroke(vk_F8);
if
s = 'F9' then keystroke(vk_F9);
if
s = 'F10' then keystroke(vk_F10);
if
s = 'F11' then keystroke(vk_F11);
if
s = 'F12' then keystroke(vk_F12);
if
s = 'LEFT' then keystroke(vk_left);
if
s = 'RIGHT' then keystroke(vk_right);
if
s = 'UP' then keystroke(vk_up);
if
s = 'DOWN' then keystroke(vk_down);
if
s = 'HOME' then keystroke(vk_home);
if
s = 'END' then keystroke(vk_end);
if
s = 'NUMLOCK' then keystroke(vk_NumLock);
if
s = 'DELETE' then keystroke(vk_Delete);
if
s = 'DEL' then keystroke(vk_Delete);
if
s = 'INS' then keystroke(vk_Insert);
if
s = 'INSERT' then keystroke(vk_Insert); end; end;
//******************************************************************* // FINDAWINDOW - Searches a Windows List in order to
locate a window // with the specified title.
If Partial is true, match doesn't need to //
be the exact title. If partial is false, the given title must match // the window title exactly. The WList parameter is the
Window list declared // in the calling form.
This procedure requires the WINDOWLIST unit, // available from www.torry.ru //******************************************************************** Function FindaWindow(title : string; partial : boolean; wlist : TWindowList): hwnd; var winnum : integer; foundit : boolean; begin wlist.refresh; //
refresh the windows list winnum := 0; //
initialize counter foundit := false;
ifnot partial then begin repeat if
uppercase(wlist.windows[winnum].wincaption) = uppercase(title) then begin foundit := true;
//result := wlist.windows[winnum].winhandle; end else begin inc(winnum)
end;
until foundit or (winnum = (wlist.count-1));
end else// partial title
search begin repeat if
isinstring(uppercase(title),uppercase(wlist.windows[winnum].wincaption))
then begin foundit := true;
end else begin inc(winnum)
end;
until foundit or (winnum = (wlist.count-1));
end; ifnot foundit then result := 0 //return 0 if no window matched else result := wlist.windows[winnum].winhandle; end; end.