sendmessage等估计解决不了问题,最好使用键盘钩子,我这里有个例子完全可以实现:<br>unit SendKey;<br><br>interface<br><br>uses<br> SysUtils, Windows, Messages, Classes, KeyDefs;<br><br>type<br> { Error codes }<br> TSendKeyError = (sk_None, sk_FailSetHook, sk_InvalidToken, sk_UnknownError,<br> sk_AlreadyPlaying);<br> { first vk code to last vk code }<br> TvkKeySet = set of vk_LButton..vk_Scroll;<br><br> { exceptions }<br> ESendKeyError = class(Exception);<br> ESKSetHookError = class(ESendKeyError);<br> ESKInvalidToken = class(ESendKeyError);<br> ESKAlreadyPlaying = class(ESendKeyError);<br><br>function SendKeys(S: String): TSendKeyError;<br>procedure WaitForHook;<br>procedure StopPlayback;<br><br>var<br> Playing: Boolean = False;<br><br>implementation<br><br>uses Forms;<br><br>type<br> { a TList descendant that know how to dispose of its contents }<br> TMessageList = class(TList)<br> public<br> destructor Destroy; override;<br> end;<br><br>const<br> { valid "sys" keys }<br> vkKeySet: TvkKeySet = [Ord('A')..Ord('Z'), vk_Menu, vk_F1..vk_F12];<br><br>destructor TMessageList.Destroy;<br>var<br> i: longint;<br>begin<br> { deallocate all the message records before discarding the list }<br> for i := 0 to Count - 1 do<br> Dispose(PEventMsg(Items));<br> inherited Destroy;<br>end;<br><br>var<br> { variables global to the DLL }<br> MsgCount: word = 0;<br> MessageBuffer: TEventMsg;<br> HookHandle: hHook = 0;<br> MessageList: TMessageList = Nil;<br> AltPressed, ControlPressed, ShiftPressed: Boolean;<br><br>procedure StopPlayback;<br>{ Unhook the hook, and clean up }<br>begin<br> { if Hook is currently active, then unplug it }<br> if Playing then<br> UnhookWindowsHookEx(HookHandle);<br> MessageList.Free;<br> Playing := False;<br>end;<br><br>function Play(Code: integer; wParam, lParam: Longint): Longint; stdcall;<br>{ This is the JournalPlayback callback function. It is called by Windows }<br>{ when Windows polls for hardware events. The code parameter indicates what }<br>{ to do. }<br>begin<br> case Code of<br><br> hc_Skip: begin<br> { hc_Skip means to pull the next message out of our list. If we }<br> { are at the end of the list, it's okay to unhook the JournalPlayback }<br> { hook from here. }<br> { increment message counter }<br> inc(MsgCount);<br> { check to see if all messages have been played }<br> if MsgCount >= MessageList.Count then<br> StopPlayback<br> else<br> { copy next message from list into buffer }<br> MessageBuffer := TEventMsg(MessageList.Items[MsgCount]^);<br> Result := 0;<br> end;<br><br> hc_GetNext: begin<br> { hc_GetNext means to fill the wParam and lParam with the proper }<br> { values so that the message can be played back. DO NOT unhook }<br> { hook from within here. Return value indicates how much time until }<br> { Windows should playback message. We'll return 0 so that it's }<br> { processed right away. }<br> { move message in buffer to message queue }<br> PEventMsg(lParam)^ := MessageBuffer;<br> Result := 0 { process immediately }<br> end<br><br> else<br> { if Code isn't hc_Skip or hc_GetNext, then call next hook in chain }<br> Result := CallNextHookEx(HookHandle, Code, wParam, lParam);<br> end;<br>end;<br><br>procedure StartPlayback;<br>begin<br> MessageBuffer := TEventMsg(MessageList.Items[0]^);<br> MsgCount := 0;<br> AltPressed := False;<br> ControlPressed := False;<br> ShiftPressed := False;<br> HookHandle := SetWindowsHookEx(wh_JournalPlayback, Play, hInstance, 0);<br> if HookHandle = 0 then<br> raise ESKSetHookError.Create('Couldn''t set hook')<br> else<br> Playing := True;<br>end;<br><br>procedure MakeMessage(vKey: byte; M: Cardinal);<br>var<br> E: PEventMsg;<br>begin<br> New(E);<br> with E^ do begin<br> message := M;<br> paramL := vKey;<br> paramH := MapVirtualKey(vKey, 0);<br> time := GetTickCount;<br> hwnd := 0;<br> end;<br> MessageList.Add(E);<br>end;<br><br>procedure KeyDown(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 KeyUp(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<br> KeyDown(vk_Menu);<br> if ControlPressed then<br> KeyDown(vk_Control);<br> if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) or ShiftPressed then<br> KeyDown(vk_Shift);<br> KeyDown(Lo(VKeyCode));<br> KeyUp(Lo(VKeyCode));<br> if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) or ShiftPressed then<br> KeyUp(vk_Shift);<br> if ShiftPressed then begin<br> ShiftPressed := False;<br> end;<br> if ControlPressed then begin<br> KeyUp(vk_Control);<br> ControlPressed := False;<br> end;<br> if AltPressed then begin<br> KeyUp(vk_Menu);<br> AltPressed := False;<br> end;<br>end;<br><br>procedure ProcessKey(S: String);<br>var<br> KeyCode: word;<br> Key: byte;<br> index: integer;<br> Token: TKeyString;<br>begin<br> index := 1;<br> repeat<br> case S[index] of<br> KeyGroupOpen : begin<br> Token := '';<br> inc(index);<br> while S[index] <> KeyGroupClose do begin<br> Token := Token + S[index];<br> inc(index);<br> if (Length(Token) = 7) and (S[index] <> KeyGroupClose) then<br> raise ESKInvalidToken.Create('No closing brace');<br> end;<br> if not FindKeyInArray(Token, Key) then<br> raise ESKInvalidToken.Create('Invalid token');<br> SimKeyPresses(MakeWord(Key, 0));<br> end;<br><br> AltKey : begin<br> AltPressed := True;<br> end;<br><br> ControlKey : begin<br> ControlPressed := True;<br> end;<br><br> ShiftKey : begin<br> ShiftPressed := True;<br> end;<br><br> else begin<br> KeyCode := vkKeyScan(S[index]);<br> SimKeyPresses(KeyCode);<br> end;<br> end;<br> inc(index);<br> until index > Length(S);<br>end;<br><br>procedure WaitForHook;<br>begin<br> repeat Application.ProcessMessages until not Playing;<br>end;<br><br>function SendKeys(S: String): TSendKeyError;<br>begin<br> Result := sk_None;<br> try<br> if Playing then raise ESKAlreadyPlaying.Create('');<br> MessageList := TMessageList.Create;<br> ProcessKey(S);<br> StartPlayback;<br> except<br> on E:ESendKeyError do begin<br> MessageList.Free;<br> if E is ESKSetHookError then<br> Result := sk_FailSetHook<br> else if E is ESKInvalidToken then<br> Result := sk_InvalidToken<br> else if E is ESKAlreadyPlaying then<br> Result := sk_AlreadyPlaying;<br> end<br> else<br> Result := sk_UnknownError;<br> end;<br>end;<br><br>end.<br>---------------------------------------<br>unit Keydefs;<br><br>interface<br><br>uses Windows;<br><br>const<br> MaxKeys = 24;<br> ControlKey = '^';<br> AltKey = '@';<br> ShiftKey = '~';<br> KeyGroupOpen = '{';<br> KeyGroupClose = '}';<br><br>type<br> TKeyString = String[7];<br><br> TKeyDef = record<br> Key: TKeyString;<br> vkCode: Byte;<br> end;<br><br>const<br> KeyDefArray : array[1..MaxKeys] of TKeyDef = (<br> (Key: 'F1'; vkCode: vk_F1),<br> (Key: 'F2'; vkCode: vk_F2),<br> (Key: 'F3'; vkCode: vk_F3),<br> (Key: 'F4'; vkCode: vk_F4),<br> (Key: 'F5'; vkCode: vk_F5),<br> (Key: 'F6'; vkCode: vk_F6),<br> (Key: 'F7'; vkCode: vk_F7),<br> (Key: 'F8'; vkCode: vk_F8),<br> (Key: 'F9'; vkCode: vk_F9),<br> (Key: 'F10'; vkCode: vk_F10),<br> (Key: 'F11'; vkCode: vk_F11),<br> (Key: 'F12'; vkCode: vk_F12),<br> (Key: 'INSERT'; vkCode: vk_Insert),<br> (Key: 'DELETE'; vkCode: vk_Delete),<br> (Key: 'HOME'; vkCode: vk_Home),<br> (Key: 'END'; vkCode: vk_End),<br> (Key: 'PGUP'; vkCode: vk_Prior),<br> (Key: 'PGDN'; vkCode: vk_Next),<br> (Key: 'TAB'; vkCode: vk_Tab),<br> (Key: 'ENTER'; vkCode: vk_Return),<br> (Key: 'BKSP'; vkCode: vk_Back),<br> (Key: 'PRTSC'; vkCode: vk_SnapShot),<br> (Key: 'SHIFT'; vkCode: vk_Shift),<br> (Key: 'ESCAPE'; vkCode: vk_Escape));<br><br><br>function FindKeyInArray(Key: TKeyString; var Code: Byte): Boolean;<br><br>implementation<br><br>uses SysUtils;<br><br>function FindKeyInArray(Key: TKeyString; var Code: Byte): Boolean;<br>{ function searches array for token passed in Key, and returns the }<br>{ virtual key code in Code. }<br>var<br> i: word;<br>begin<br> Result := False;<br> for i := Low(KeyDefArray) to High(KeyDefArray) do<br> if UpperCase(Key) = KeyDefArray.Key then begin<br> Code := KeyDefArray.vkCode;<br> Result := True;<br> Break;<br> end;<br>end;<br><br>end.<br><br>for example:<br>unit Unit1;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> Dialogs, StdCtrls, SendKey,KeyDefs;<br><br>type<br> TForm1 = class(TForm)<br> Button1: TButton;<br> procedure Button1Click(Sender: TObject);<br> procedure FormKeyDown(Sender: TObject; var Key: Word;<br> Shift: TShiftState);<br> private<br> { Private declarations }<br> public<br> { Public declarations }<br> end;<br><br>var<br> Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> SendKeys('{F1}');<br>end;<br><br>procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;<br> Shift: TShiftState);<br>begin<br> if Key=112 then ShowMessage('F1');<br>end;<br><br>end.<br><br>注意:form1.keypreview:=true;<br><br>如果向其他程序发送:<br> H := FindWindow('Caption', nil); // find window<br> if SetForegroundWindow(H) then // bring it to front<br> SendKeys('{F1}');