比如 Ctrl + End ??
向一个非可视窗口发送这个按键消息。
不要用keybd_event API.
请不要发送同本问题无关的内容,谢谢!

解决方案 »

  1.   

    那么说一个非可视的窗体就不能关闭的了??
    不是这么说的吧。听人说可以用sendmessage(......);
    里面有个参数我不知道该如何设置。
      

  2.   

    我知道用WM_KeyDown啊。 可是组合键该用什么值?
      

  3.   

    用各键的或运算  or  ( VK_CONTROL or VK_END )
    接收的时候用与运算 and
      如果 ((Key and VK_CONTROL)=VK_CONTROL) and 
           ((Key and VK_CONTROL)=VK_CONTROL)
      那么就是按下了Ctrl键+ End键
      

  4.   

    下面的代码是模拟Ctrl+C和Ctrl+V: 
    //Ctrl+C:keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), 0, 0);keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), KEYEVENTF_KEYUP, 0);keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0)//Ctrl+V:keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), 0, 0);keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), KEYEVENTF_KEYUP, 0);keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0)**************************按下一个键最好用SendMessage,用sndkey32.pas无疑会增加程序尺寸。组合键(超过两个以上)用sndkey32.pas就显出优势来了。另一种解决方法,下例模拟按下Alt+Down,可参见Delphi SDK的帮助:keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt downkeybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key downkeybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key upkeybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up让 WIN95 模拟按了一个按键,例如按下 ENTER或者 TAB 键?PostMessage(Object.Handle, WM_KEYDOWN, VK_TAB, 0);////////////////////////////////unit Unit1;interfaceusesSysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls;typeTForm1 = class(TForm)Button1: TButton;Button2: TButton;procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure FormKeyPress(Sender: TObject; var Key: Char);privateAppInst: THandle;AppWind: THandle;public{ Public declarations }end;varForm1: TForm1;implementation{$R *.DFM}uses ShellAPI; procedure SendShift(H: HWnd; Down: Boolean);var vKey, ScanCode, wParam: Word;lParam: longint;beginvKey:= $10;ScanCode:= MapVirtualKey(vKey, 0);wParam:= vKey or ScanCode shl 8;lParam:= longint(ScanCode) shl 16 or 1;if not(Down) then lParam:= lParam or $C0000000;SendMessage(H, WM_KEYDOWN, vKey, lParam);end;procedure SendCtrl(H: HWnd; Down: Boolean);var vKey, ScanCode, wParam: Word;lParam: longint;beginvKey:= $11;ScanCode:= MapVirtualKey(vKey, 0);wParam:= vKey or ScanCode shl 8;lParam:= longint(ScanCode) shl 16 or 1;if not(Down) then lParam:= lParam or $C0000000;SendMessage(H, WM_KEYDOWN, vKey, lParam);end;procedure SendKey(H: Hwnd; Key: char);var vKey, ScanCode, wParam: Word;lParam, ConvKey: longint;Shift, Ctrl: boolean;beginConvKey:= OemKeyScan(ord(Key));Shift:= (ConvKey and $00020000) <> 0;Ctrl:= (ConvKey and $00040000) <> 0;ScanCode:= ConvKey and $000000FF or $FF00;vKey:= ord(Key);wParam:= vKey;lParam:= longint(ScanCode) shl 16 or 1;if Shift then SendShift(H, true);if Ctrl then SendCtrl(H, true);SendMessage(H, WM_KEYDOWN, vKey, lParam);SendMessage(H, WM_CHAR, vKey, lParam);lParam:= lParam or $C0000000;SendMessage(H, WM_KEYUP, vKey, lParam);if Shift then SendShift(H, false);if Ctrl then SendCtrl(H, false);end; 
      

  5.   

    function EnumFunc(Handle: HWnd; TF: TForm1): Bool; Far;beginTF.AppWind:= 0;if GetWindowWord(Handle, GWW_HINSTANCE) = TF.AppInst thenTF.AppWind:= Handle;result:= (TF.AppWind = 0);end;procedure TForm1.Button1Click(Sender: TObject);var Text: Array[0..255] of char;beginAppInst:= ShellExecute(Handle, 'open', 'notepad.exe', nil, '', SW_NORMAL);EnumWindows(@EnumFunc, longint(self));AppWind:= GetWindow(AppWind, GW_CHILD);end; procedure TForm1.Button2Click(Sender: TObject);beginSendKey(AppWind, 'T');SendKey(AppWind, 'e');SendKey(AppWind, 's');SendKey(AppWind, 't');end;procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);beginif AppWind <> 0 then SendKey(AppWind, Key);end;end.///////////////////////////////////////////////////////////////////////Ah,这个嘛......正好在《DELPHI新闻组学习笔记》上看到一篇:How to send [Alt]+[Down]?--------------发出一个Alt+Down 组合键Re:Use the keybd_event API function to fake keyboard events. Note that eachkey down event needs a matching key up or you mess up the key state array.keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt downkeybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key downkeybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key upkeybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up经本人试验,确实可行,另加补充:Ctrl: VK_CONTROLSHIFT:VK_SHIFTTAB: VK_TAB'A': byte('A') (98-6-8 22:28)/////////////////////////////////////////////////////////////(*Converts a string of characters and key names to keyboard events andpasses them to Windows.Example syntax:SendKeys('abc123{left}{left}{left}def{end}456{left 6}ghi{end}789', True);*)Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;typeWBytes = array[0..pred(SizeOf(Word))] of Byte;TSendKey = recordName : ShortString;VKey : Byte;end;const{Array of keys that SendKeys recognizes.If you add to this list, you must be sure to keep it sorted alphabeticallyby Name because a binary search routine is used to scan it.}MaxSendKeyRecs = 41;SendKeyRecs : array[1..MaxSendKeyRecs] of TSendKey =((Name:'BKSP'; VKey:VK_BACK),(Name:'BS'; VKey:VK_BACK),(Name:'BACKSPACE'; VKey:VK_BACK),(Name:'BREAK'; VKey:VK_CANCEL),(Name:'CAPSLOCK'; VKey:VK_CAPITAL),(Name:'CLEAR'; VKey:VK_CLEAR),(Name:'DEL'; VKey:VK_DELETE),(Name:'DELETE'; VKey:VK_DELETE),(Name:'DOWN'; VKey:VK_DOWN),(Name:'END'; VKey:VK_END),(Name:'ENTER'; VKey:VK_RETURN),(Name:'ESC'; VKey:VK_ESCAPE),(Name:'ESCAPE'; VKey:VK_ESCAPE),(Name:'F1'; VKey:VK_F1),(Name:'F10'; VKey:VK_F10),(Name:'F11'; VKey:VK_F11),(Name:'F12'; VKey:VK_F12),(Name:'F13'; VKey:VK_F13),(Name:'F14'; VKey:VK_F14),(Name:'F15'; VKey:VK_F15),(Name:'F16'; VKey:VK_F16),(Name:'F2'; VKey:VK_F2),(Name:'F3'; VKey:VK_F3),(Name:'F4'; VKey:VK_F4),(Name:'F5'; VKey:VK_F5),(Name:'F6'; VKey:VK_F6),(Name:'F7'; VKey:VK_F7),(Name:'F8'; VKey:VK_F8),(Name:'F9'; VKey:VK_F9),(Name:'HELP'; VKey:VK_HELP),(Name:'HOME'; VKey:VK_HOME),(Name:'INS'; VKey:VK_INSERT),(Name:'LEFT'; VKey:VK_LEFT),(Name:'NUMLOCK'; VKey:VK_NUMLOCK),(Name:'PGDN'; VKey:VK_NEXT),(Name:'PGUP'; VKey:VK_PRIOR),(Name:'PRTSC'; VKey:VK_PRINT),(Name:'RIGHT'; VKey:VK_RIGHT),(Name:'SCROLLLOCK'; VKey:VK_SCROLL),(Name:'TAB'; VKey:VK_TAB),(Name:'UP'; VKey:VK_UP));{Extra VK constants missing from Delphi's Windows API interface}VK_NULL=0;VK_SemiColon=186;VK_Equal=187;VK_Comma=188;VK_Minus=189;VK_Period=190;VK_Slash=191;VK_BackQuote=192;VK_LeftBracket=219;VK_BackSlash=220;VK_RightBracket=221;VK_Quote=222;VK_Last=VK_Quote;ExtendedVKeys : set of byte =[VK_Up,VK_Down,VK_Left,VK_Right,VK_Home,VK_End,VK_Prior, {PgUp}VK_Next, {PgDn}VK_Insert,VK_Delete];constINVALIDKEY = $FFFF {Unsigned -1};VKKEYSCANSHIFTON = $01;VKKEYSCANCTRLON = $02;VKKEYSCANALTON = $04;UNITNAME = 'SendKeys';varUsingParens, ShiftDown, ControlDown, AltDown, FoundClose : Boolean;PosSpace : Byte;I, L : Integer;NumTimes, MKey : Word;KeyString : String[20];procedure DisplayMessage(Message : PChar);beginMessageBox(0,Message,UNITNAME,0);end;
      

  6.   

    function BitSet(BitTable, BitMask : Byte) : Boolean;beginResult:=ByteBool(BitTable and BitMask);end;procedure SetBit(var BitTable : Byte; BitMask : Byte);beginBitTable:=BitTable or Bitmask;end;Procedure KeyboardEvent(VKey, ScanCode : Byte; Flags : Longint);varKeyboardMsg : TMsg;beginkeybd_event(VKey, ScanCode, Flags,0);If (Wait) then While (PeekMessage(KeyboardMsg,0,WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) do beginTranslateMessage(KeyboardMsg);DispatchMessage(KeyboardMsg);end;end;Procedure SendKeyDown(VKey: Byte; NumTimes : Word; GenUpMsg : Boolean);varCnt : Word;ScanCode : Byte;NumState : Boolean;KeyBoardState : TKeyboardState;beginIf (VKey=VK_NUMLOCK) then beginNumState:=ByteBool(GetKeyState(VK_NUMLOCK) and 1);GetKeyBoardState(KeyBoardState);If NumState then KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] and not 1)else KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] or 1);SetKeyBoardState(KeyBoardState);exit;end;ScanCode:=Lo(MapVirtualKey(VKey,0));For Cnt:=1 to NumTimes doIf (VKey in ExtendedVKeys)then beginKeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY);If (GenUpMsg) thenKeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)end else beginKeyboardEvent(VKey, ScanCode, 0);If (GenUpMsg) then KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);end;end;Procedure SendKeyUp(VKey: Byte);varScanCode : Byte;beginScanCode:=Lo(MapVirtualKey(VKey,0));If (VKey in ExtendedVKeys)thenKeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)else KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);end;Procedure SendKey(MKey: Word; NumTimes : Word; GenDownMsg : Boolean);beginIf (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyDown(VK_SHIFT,1,False);If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyDown(VK_CONTROL,1,False);If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyDown(VK_MENU,1,False);SendKeyDown(Lo(MKey), NumTimes, GenDownMsg);If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyUp(VK_SHIFT);If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyUp(VK_CONTROL);If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyUp(VK_MENU);end;{Implements a simple binary search to locate special key name strings}Function StringToVKey(KeyString : ShortString) : Word;varFound, Collided : Boolean;Bottom, Top, Middle : Byte;beginResult:=INVALIDKEY;Bottom:=1;Top:=MaxSendKeyRecs;Found:=false;Middle:=(Bottom+Top) div 2;RepeatCollided:=((Bottom=Middle) or (Top=Middle));If (KeyString=SendKeyRecs[Middle].Name) then beginFound:=True;Result:=SendKeyRecs[Middle].VKey;end else beginIf (KeyString>SendKeyRecs[Middle].Name) then Bottom:=Middleelse Top:=Middle;Middle:=(Succ(Bottom+Top)) div 2;end;Until (Found or Collided);If (Result=INVALIDKEY) then DisplayMessage('Invalid Key Name');end;procedure PopUpShiftKeys;beginIf (not UsingParens) then beginIf ShiftDown then SendKeyUp(VK_SHIFT);If ControlDown then SendKeyUp(VK_CONTROL);If AltDown then SendKeyUp(VK_MENU);ShiftDown:=false;ControlDown:=false;AltDown:=false;end;end;beginAllocationSize:=MaxInt;Result:=false;UsingParens:=false;ShiftDown:=false;ControlDown:=false;AltDown:=false;I:=0;L:=StrLen(SendKeysString);If (L>AllocationSize) then L:=AllocationSize;If (L=0) then Exit;While (IINVALIDKEY) then beginSendKey(MKey,1,True);PopUpShiftKeys;end else DisplayMessage('Invalid KeyName');Inc(I);end;end;end;Result:=true;PopUpShiftKeys;end;**************************************{//虚拟按键调用方法:SendKey(VK_ESCAPE,[]);}procedure SendKey(const mKey: Word; mShiftState: TShiftState;mCount: Integer = 1); { 模拟系统按键;mCount指定按键次数 }constcExtended: set of Byte = [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_HOME,VK_END, VK_PRIOR, VK_NEXT, VK_INSERT, VK_DELETE];procedure pKeyboardEvent(mKey, mScanCode: Byte; mFlags: Longint);varvKeyboardMsg: TMsg;beginkeybd_event(mKey, mScanCode, mFlags, 0);while PeekMessage(vKeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) dobeginTranslateMessage(vKeyboardMsg);DispatchMessage(vKeyboardMsg);end;end; { pKeyboardEvent }procedure pSendKeyDown(mKey: Word; mGenUpMsg: Boolean);varvScanCode: Byte;vNumState: Boolean;vKeyBoardState: TKeyboardState;beginif (mKey = VK_NUMLOCK) then beginvNumState := ByteBool(GetKeyState(VK_NUMLOCK) and 1);GetKeyBoardState(vKeyBoardState);if vNumState thenvKeyBoardState[VK_NUMLOCK] := (vKeyBoardState[VK_NUMLOCK] and not 1)else vKeyBoardState[VK_NUMLOCK] := (vKeyBoardState[VK_NUMLOCK] or 1);SetKeyBoardState(vKeyBoardState);Exit;end;vScanCode := Lo(MapVirtualKey(mKey, 0));if (mKey in cExtended) then beginpKeyboardEvent(mKey, vScanCode, KEYEVENTF_EXTENDEDKEY);if mGenUpMsg thenpKeyboardEvent(mKey, vScanCode,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)end else beginpKeyboardEvent(mKey, vScanCode, 0);if mGenUpMsg then pKeyboardEvent(mKey, vScanCode, KEYEVENTF_KEYUP);end;end; { pSendKeyDown }procedure pSendKeyUp(mKey: Word);varvScanCode: Byte;beginvScanCode := Lo(MapVirtualKey(mKey, 0));if mKey in cExtended thenpKeyboardEvent(mKey, vScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)else pKeyboardEvent(mKey, vScanCode, KEYEVENTF_KEYUP);end; { pSendKeyUp }varI: Integer;beginfor I := 1 to mCount do beginif ssShift in mShiftState then pSendKeyDown(VK_SHIFT, False);if ssCtrl in mShiftState then pSendKeyDown(VK_CONTROL, False);if ssAlt in mShiftState then pSendKeyDown(VK_MENU, False);pSendKeyDown(mKey, True);if ssShift in mShiftState then pSendKeyUp(VK_SHIFT);if ssCtrl in mShiftState then pSendKeyUp(VK_CONTROL);if ssAlt in mShiftState then pSendKeyUp(VK_MENU);end;end; { SendKey }