unit SendKey;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes;<br><br>var<br> Playing: Boolean;<br><br>function SendKeys(S: string): Boolean;<br>procedure StopPlayback;<br><br>implementation<br><br>uses Keydefs;<br><br>type<br> TvkKeySet = set of vk_LButton..vk_Scroll;<br> <br> TMessageList = class(TList)<br> public<br> destructor Destroy; override;<br> end;<br><br>const<br> vkKeySet: TvkKeySet = [Ord('A')..Ord('Z'), vk_Menu, vk_F1..vk_F12];<br><br>{ TMessageList }<br><br>destructor TMessageList.Destroy;<br>var<br> I: Longint;<br>begin<br> for I := 0 to Count - 1 do<br> Dispose(PEventMsg(Items));<br> inherited Destroy;<br>end;<br><br>var<br>// RecordingPaused: Boolean;<br> PlayCount: WORD;<br> PlayBuffer: TEventMsg;<br> PlayHandle: hHook;<br> PlayList: TMessageList;<br> AltPressed, ControlPressed, ShiftPressed: Boolean;<br><br>function KeyRecord(Code: Integer; wParam, lParam: Longint): Longint; stdcall;<br>begin<br> if Code = HC_ACTION then<br> begin<br><br> Result := 0;<br> end<br> else<br> Result := CallNextHookEx(RecHandle, Code, wParam, lParam);<br>end;<br><br>function Play(Code: Integer; wParam, lParam: Longint): Longint; stdcall;<br>begin<br> case Code of<br> HC_SKIP:<br> begin<br> Inc(PlayCount);<br> if PlayCount >= PlayList.Count then //StopPlayback<br> else PlayBuffer := TEventMsg(PlayList.Items[PlayCount]^);<br> Result := 0;<br> end;<br> HC_GETNEXT:<br> begin<br> PEventMsg(lParam)^ := PlayBuffer;<br> Result := 0<br> end<br> else<br> Result := CallNextHookEx(PlayHandle, Code, wParam, lParam);<br> end;<br>end;<br><br>procedure StartPlayback;<br>begin<br> PlayBuffer := TEventMsg(PlayList.Items[0]^);<br> PlayCount := 0;<br> AltPressed := False;<br> ControlPressed := False;<br> ShiftPressed := False;<br> PlayHandle := SetWindowsHookEx(wh_JournalPlayback, Play, hInstance, 0);<br> if PlayHandle = 0 then<br> raise Exception.Create('Failed to set hook!');<br> Playing := True;<br>end;<br><br>procedure StopPlayback;<br>begin<br> if Playing then<br> UnhookWindowsHookEx(PlayHandle);<br> PlayList.Free;<br> Playing := False;<br>end;<br><br>procedure MakeMessage(vKey: byte; M: Cardinal);<br>var<br> E: PEventMsg;<br>begin<br> New(E);<br> with E^ do<br> begin<br> message := M;<br> paramL := vKey;<br> paramH := MapVirtualKey(vKey, 0);<br> time := GetTickCount;<br> hwnd := 0;<br> end;<br> PlayList.Add(E);<br>end;<br><br>procedure GenKeyDown(vKey: Byte);<br>begin<br> if AltPressed and (not ControlPressed) and (vKey in vkKeySet) then<br> MakeMessage(vKey, WM_SYSKEYDOWN)<br> else<br> MakeMessage(vKey, WM_KEYDOWN);<br>end;<br><br>procedure GenKeyUp(vKey: Byte);<br>begin<br> if AltPressed and (not ControlPressed) and (vKey in vkKeySet) then<br> MakeMessage(vKey, WM_SYSKEYUP)<br> else<br> MakeMessage(vKey, WM_KEYUP);<br>end;<br><br>procedure SimKeyPresses(VKeyCode: Word);<br>begin<br> if AltPressed then GenKeyDown(vk_Menu);<br> if ControlPressed then GenKeyDown(vk_Control);<br> if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed))<br> or ShiftPressed then<br> GenKeyDown(vk_Shift);<br> GenKeyDown(Lo(VKeyCode));<br> GenKeyUp(Lo(VKeyCode));<br> if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed))<br> or ShiftPressed then<br> GenKeyUp(vk_Shift);<br> if ShiftPressed then ShiftPressed := False;<br> if ControlPressed then<br> begin<br> GenKeyUp(vk_Control);<br> ControlPressed := False;<br> end;<br> if AltPressed then<br> begin<br> GenKeyUp(vk_Menu);<br> AltPressed := False;<br> end;<br>end;<br><br>procedure ProcessPlayKey(S: string);<br>var<br> KeyCode: Word;<br> Key: Byte;<br> I: Integer;<br> Token: TKeyString;<br>begin<br> I := 1;<br> repeat<br> case S of<br> KeyGroupOpen:<br> begin<br> Token := '';<br> Inc(I);<br> while S <> KeyGroupClose do begin<br> Token := Token + S;<br> Inc(I);<br> if (Length(Token) = 7) and (S <> KeyGroupClose) then<br> raise Exception.Create('No closing brace');<br> end;<br> if not FindKeyInArray(Token, Key) then<br> raise Exception.Create('Invalid token');<br> SimKeyPresses(MakeWord(Key, 0));<br> end;<br> AltKey: AltPressed := True;<br> ControlKey: ControlPressed := True;<br> ShiftKey: ShiftPressed := True;<br> else begin<br> KeyCode := vkKeyScan(S);<br> SimKeyPresses(KeyCode);<br> end;<br> end;<br> Inc(I);<br> until I > Length(S);<br>end;<br><br>function SendKeys(S: string): Boolean;<br>begin<br> Result := False;<br> try<br> if Playing then Exit;<br> PlayList := PlayList.Create;<br> ProcessPlayKey(S);<br> StartPlayback;<br> Result := True;<br> except<br> end;<br>end;<br>{<br>procedure WaitForPlay;<br>begin<br> repeat<br> Application.ProcessMessages;<br> until not Playing;<br>end;}<br><br>end.<br>