按下一个键最好用SendMessage,用sndkey32.pas无疑会增加程序尺寸。<br>组合键(超过两个以上)用sndkey32.pas就显出优势来了。<br><br>另一种解决方法,下例模拟按下Alt+Down,可参见Delphi SDK的帮助:<br> keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt down <br> keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key down <br> keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key up <br> keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up <br><br>让 WIN95 模拟按了一个按键,例如按下 ENTER或者 TAB 键?<br>PostMessage(Object.Handle, WM_KEYDOWN, VK_TAB, 0);<br><br>////////////////////////////////<br>unit Unit1;<br><br>interface<br><br>uses<br> SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,<br> Forms, Dialogs, StdCtrls;<br><br>type<br> TForm1 = class(TForm)<br> Button1: TButton;<br> Button2: TButton;<br> procedure Button1Click(Sender: TObject);<br> procedure Button2Click(Sender: TObject);<br> procedure FormKeyPress(Sender: TObject; var Key: Char);<br> private<br> AppInst: THandle;<br> AppWind: THandle;<br> public<br> { Public declarations }<br> end;<br><br>var<br> Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>uses ShellAPI;<br> <br><br>procedure SendShift(H: HWnd; Down: Boolean);<br>var vKey, ScanCode, wParam: Word;<br> lParam: longint;<br>begin<br> vKey:= $10;<br> ScanCode:= MapVirtualKey(vKey, 0);<br> wParam:= vKey or ScanCode shl 8;<br> lParam:= longint(ScanCode) shl 16 or 1;<br> if not(Down) then lParam:= lParam or $C0000000;<br> SendMessage(H, WM_KEYDOWN, vKey, lParam);<br>end;<br><br>procedure SendCtrl(H: HWnd; Down: Boolean);<br>var vKey, ScanCode, wParam: Word;<br> lParam: longint;<br>begin<br> vKey:= $11;<br> ScanCode:= MapVirtualKey(vKey, 0);<br> wParam:= vKey or ScanCode shl 8;<br> lParam:= longint(ScanCode) shl 16 or 1;<br> if not(Down) then lParam:= lParam or $C0000000;<br> SendMessage(H, WM_KEYDOWN, vKey, lParam);<br>end;<br><br>procedure SendKey(H: Hwnd; Key: char);<br>var vKey, ScanCode, wParam: Word;<br> lParam, ConvKey: longint;<br> Shift, Ctrl: boolean;<br>begin<br> ConvKey:= OemKeyScan(ord(Key));<br> Shift:= (ConvKey and $00020000) <> 0;<br> Ctrl:= (ConvKey and $00040000) <> 0;<br> ScanCode:= ConvKey and $000000FF or $FF00;<br> vKey:= ord(Key);<br> wParam:= vKey;<br> lParam:= longint(ScanCode) shl 16 or 1;<br> if Shift then SendShift(H, true);<br> if Ctrl then SendCtrl(H, true);<br> SendMessage(H, WM_KEYDOWN, vKey, lParam);<br> SendMessage(H, WM_CHAR, vKey, lParam);<br> lParam:= lParam or $C0000000;<br> SendMessage(H, WM_KEYUP, vKey, lParam);<br> if Shift then SendShift(H, false);<br> if Ctrl then SendCtrl(H, false);<br>end;<br><br>function EnumFunc(Handle: HWnd; TF: TForm1): Bool; Far;<br>begin<br> TF.AppWind:= 0;<br> if GetWindowWord(Handle, GWW_HINSTANCE) = TF.AppInst then<br> TF.AppWind:= Handle;<br> result:= (TF.AppWind = 0);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var Text: Array[0..255] of char;<br>begin<br> AppInst:= ShellExecute(Handle, 'open', 'notepad.exe', nil, '', SW_NORMAL);<br> EnumWindows(@EnumFunc, longint(self));<br> AppWind:= GetWindow(AppWind, GW_CHILD);<br>end;<br><br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br> SendKey(AppWind, 'T');<br> SendKey(AppWind, 'e');<br> SendKey(AppWind, 's');<br> SendKey(AppWind, 't');<br>end;<br><br>procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);<br>begin<br> if AppWind <> 0 then SendKey(AppWind, Key);<br>end;<br><br>end.<br>///////////////////////////////////////////////////////////////////////<br>Ah,这个嘛......正好在《DELPHI新闻组学习笔记》上看到一篇:<br>How to send [Alt]+[Down]?--------------发出一个Alt+Down 组合键 <br><br>Re: <br>Use the keybd_event API function to fake keyboard events. Note that each <br>key down event needs a matching key up or you mess up the key state array. <br><br> keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt down <br> keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key down <br> keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key up <br> keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up <br><br>经本人试验,确实可行,另加补充:<br>Ctrl: VK_CONTROL<br>SHIFT:VK_SHIFT<br>TAB: VK_TAB<br>'A': byte('A') (98-6-8 22:28)<br>/////////////////////////////////////////////////////////////<br>(*<br>Converts a string of characters and key names to keyboard events and<br>passes them to Windows.<br><br>Example syntax:<br><br>SendKeys('abc123{left}{left}{left}def{end}456{left 6}ghi{end}789', True);<br><br>*)<br><br>Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;<br>type<br> WBytes = array[0..pred(SizeOf(Word))] of Byte;<br><br> TSendKey = record<br> Name : ShortString;<br> VKey : Byte;<br> end;<br><br>const<br> {Array of keys that SendKeys recognizes.<br><br> If you add to this list, you must be sure to keep it sorted alphabetically<br> by Name because a binary search routine is used to scan it.}<br><br> MaxSendKeyRecs = 41;<br> SendKeyRecs : array[1..MaxSendKeyRecs] of TSendKey =<br> (<br> (Name:'BKSP'; VKey:VK_BACK),<br> (Name:'BS'; VKey:VK_BACK),<br> (Name:'BACKSPACE'; VKey:VK_BACK),<br> (Name:'BREAK'; VKey:VK_CANCEL),<br> (Name:'CAPSLOCK'; VKey:VK_CAPITAL),<br> (Name:'CLEAR'; VKey:VK_CLEAR),<br> (Name:'DEL'; VKey:VK_DELETE),<br> (Name:'DELETE'; VKey:VK_DELETE),<br> (Name:'DOWN'; VKey:VK_DOWN),<br> (Name:'END'; VKey:VK_END),<br> (Name:'ENTER'; VKey:VK_RETURN),<br> (Name:'ESC'; VKey:VK_ESCAPE),<br> (Name:'ESCAPE'; VKey:VK_ESCAPE),<br> (Name:'F1'; VKey:VK_F1),<br> (Name:'F10'; VKey:VK_F10),<br> (Name:'F11'; VKey:VK_F11),<br> (Name:'F12'; VKey:VK_F12),<br> (Name:'F13'; VKey:VK_F13),<br> (Name:'F14'; VKey:VK_F14),<br> (Name:'F15'; VKey:VK_F15),<br> (Name:'F16'; VKey:VK_F16),<br> (Name:'F2'; VKey:VK_F2),<br> (Name:'F3'; VKey:VK_F3),<br> (Name:'F4'; VKey:VK_F4),<br> (Name:'F5'; VKey:VK_F5),<br> (Name:'F6'; VKey:VK_F6),<br> (Name:'F7'; VKey:VK_F7),<br> (Name:'F8'; VKey:VK_F8),<br> (Name:'F9'; VKey:VK_F9),<br> (Name:'HELP'; VKey:VK_HELP),<br> (Name:'HOME'; VKey:VK_HOME),<br> (Name:'INS'; VKey:VK_INSERT),<br> (Name:'LEFT'; VKey:VK_LEFT),<br> (Name:'NUMLOCK'; VKey:VK_NUMLOCK),<br> (Name:'PGDN'; VKey:VK_NEXT),<br> (Name:'PGUP'; VKey:VK_PRIOR),<br> (Name:'PRTSC'; VKey:VK_PRINT),<br> (Name:'RIGHT'; VKey:VK_RIGHT),<br> (Name:'SCROLLLOCK'; VKey:VK_SCROLL),<br> (Name:'TAB'; VKey:VK_TAB),<br> (Name:'UP'; VKey:VK_UP)<br> );<br><br> {Extra VK constants missing from Delphi's Windows API interface}<br> VK_NULL=0;<br> VK_SemiColon=186;<br> VK_Equal=187;<br> VK_Comma=188;<br> VK_Minus=189;<br> VK_Period=190;<br> VK_Slash=191;<br> VK_BackQuote=192;<br> VK_LeftBracket=219;<br> VK_BackSlash=220;<br> VK_RightBracket=221;<br> VK_Quote=222;<br> VK_Last=VK_Quote;<br><br> ExtendedVKeys : set of byte =<br> [VK_Up,<br> VK_Down,<br> VK_Left,<br> VK_Right,<br> VK_Home,<br> VK_End,<br> VK_Prior, {PgUp}<br> VK_Next, {PgDn}<br> VK_Insert,<br> VK_Delete];<br><br>const<br> INVALIDKEY = $FFFF {Unsigned -1};<br> VKKEYSCANSHIFTON = $01;<br> VKKEYSCANCTRLON = $02;<br> VKKEYSCANALTON = $04;<br> UNITNAME = 'SendKeys';<br>var<br> UsingParens, ShiftDown, ControlDown, AltDown, FoundClose : Boolean;<br> PosSpace : Byte;<br> I, L : Integer;<br> NumTimes, MKey : Word;<br> KeyString : String[20];<br><br>procedure DisplayMessage(Message : PChar);<br>begin<br> MessageBox(0,Message,UNITNAME,0);<br>end;<br><br>function BitSet(BitTable, BitMask : Byte) : Boolean;<br>begin<br> Result:=ByteBool(BitTable and BitMask);<br>end;<br><br>procedure SetBit(var BitTable : Byte; BitMask : Byte);<br>begin<br> BitTable:=BitTable or Bitmask;<br>end;<br><br>Procedure KeyboardEvent(VKey, ScanCode : Byte; Flags : Longint);<br>var<br> KeyboardMsg : TMsg;<br>begin<br> keybd_event(VKey, ScanCode, Flags,0);<br> If (Wait) then While (PeekMessage(KeyboardMsg,0,WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) do begin<br> TranslateMessage(KeyboardMsg);<br> DispatchMessage(KeyboardMsg);<br> end;<br>end;<br><br>Procedure SendKeyDown(VKey: Byte; NumTimes : Word; GenUpMsg : Boolean);<br>var<br> Cnt : Word;<br> ScanCode : Byte;<br> NumState : Boolean;<br> KeyBoardState : TKeyboardState;<br>begin<br> If (VKey=VK_NUMLOCK) then begin<br> NumState:=ByteBool(GetKeyState(VK_NUMLOCK) and 1);<br> GetKeyBoardState(KeyBoardState);<br> If NumState then KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] and not 1)<br> else KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] or 1);<br> SetKeyBoardState(KeyBoardState);<br> exit;<br> end;<br><br> ScanCode:=Lo(MapVirtualKey(VKey,0));<br> For Cnt:=1 to NumTimes do<br> If (VKey in ExtendedVKeys)then begin<br> KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY);<br> If (GenUpMsg) then<br> KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)<br> end else begin<br> KeyboardEvent(VKey, ScanCode, 0);<br> If (GenUpMsg) then KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);<br> end;<br>end;<br><br>Procedure SendKeyUp(VKey: Byte);<br>var<br> ScanCode : Byte;<br>begin<br> ScanCode:=Lo(MapVirtualKey(VKey,0));<br> If (VKey in ExtendedVKeys)then<br> KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)<br> else KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);<br>end;<br><br>Procedure SendKey(MKey: Word; NumTimes : Word; GenDownMsg : Boolean);<br>begin<br> If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyDown(VK_SHIFT,1,False);<br> If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyDown(VK_CONTROL,1,False);<br> If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyDown(VK_MENU,1,False);<br> SendKeyDown(Lo(MKey), NumTimes, GenDownMsg);<br> If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyUp(VK_SHIFT);<br> If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyUp(VK_CONTROL);<br> If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyUp(VK_MENU);<br>end;<br><br>{Implements a simple binary search to locate special key name strings}<br><br>Function StringToVKey(KeyString : ShortString) : Word;<br>var<br> Found, Collided : Boolean;<br> Bottom, Top, Middle : Byte;<br>begin<br> Result:=INVALIDKEY;<br> Bottom:=1;<br> Top:=MaxSendKeyRecs;<br> Found:=false;<br> Middle:=(Bottom+Top) div 2;<br> Repeat<br> Collided:=((Bottom=Middle) or (Top=Middle));<br> If (KeyString=SendKeyRecs[Middle].Name) then begin<br> Found:=True;<br> Result:=SendKeyRecs[Middle].VKey;<br> end else begin<br> If (KeyString>SendKeyRecs[Middle].Name) then Bottom:=Middle<br> else Top:=Middle;<br> Middle:=(Succ(Bottom+Top)) div 2;<br> end;<br> Until (Found or Collided);<br> If (Result=INVALIDKEY) then DisplayMessage('Invalid Key Name');<br>end;<br><br>procedure PopUpShiftKeys;<br>begin<br> If (not UsingParens) then begin<br> If ShiftDown then SendKeyUp(VK_SHIFT);<br> If ControlDown then SendKeyUp(VK_CONTROL);<br> If AltDown then SendKeyUp(VK_MENU);<br> ShiftDown:=false;<br> ControlDown:=false;<br> AltDown:=false;<br> end;<br>end;<br><br>begin<br> AllocationSize:=MaxInt;<br> Result:=false;<br> UsingParens:=false;<br> ShiftDown:=false;<br> ControlDown:=false;<br> AltDown:=false;<br> I:=0;<br> L:=StrLen(SendKeysString);<br> If (L>AllocationSize) then L:=AllocationSize;<br> If (L=0) then Exit;<br><br> While (IINVALIDKEY) then begin<br> SendKey(MKey,1,True);<br> PopUpShiftKeys;<br> end else DisplayMessage('Invalid KeyName');<br> Inc(I);<br> end;<br> end;<br> end;<br> Result:=true;<br> PopUpShiftKeys;<br>end;<br><br><br>