Delphi SendKeys.Pas

  1. unit sndkey32;
  2. interface
  3. Uses SysUtils, Windows, Messages;
  4. Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;
  5. function AppActivate(WindowName : PChar) : boolean;
  6. {Buffer for working with PChar's}
  7. const
  8.   WorkBufLen = 40;
  9. var
  10.   WorkBuf : array[0..WorkBufLen] of Char;
  11. implementation
  12. type
  13.   THKeys = array[0..pred(MaxLongInt)] of byte;
  14. var
  15.   AllocationSize : integer;
  16. (*
  17. Converts a string of characters and key names to keyboard events and
  18. passes them to Windows.
  19. Example syntax:
  20. SendKeys('abc123{left}{left}{left}def{end}456{left 6}ghi{end}789', True);
  21. *)
  22. Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;
  23. type
  24.   WBytes = array[0..pred(SizeOf(Word))] of Byte;
  25.   TSendKey = record
  26.     Name : ShortString;
  27.     VKey : Byte;
  28.   end;
  29. const
  30.   {Array of keys that SendKeys recognizes.
  31.   If you add to this list, you must be sure to keep it sorted alphabetically
  32.   by Name because a binary search routine is used to scan it.}
  33.   MaxSendKeyRecs = 41;
  34.   SendKeyRecs : array[1..MaxSendKeyRecs] of TSendKey =
  35.   (
  36.    (Name:'BKSP';            VKey:VK_BACK),
  37.    (Name:'BS';              VKey:VK_BACK),
  38.    (Name:'BACKSPACE';       VKey:VK_BACK),
  39.    (Name:'BREAK';           VKey:VK_CANCEL),
  40.    (Name:'CAPSLOCK';        VKey:VK_CAPITAL),
  41.    (Name:'CLEAR';           VKey:VK_CLEAR),
  42.    (Name:'DEL';             VKey:VK_DELETE),
  43.    (Name:'DELETE';          VKey:VK_DELETE),
  44.    (Name:'DOWN';            VKey:VK_DOWN),
  45.    (Name:'END';             VKey:VK_END),
  46.    (Name:'ENTER';           VKey:VK_RETURN),
  47.    (Name:'ESC';             VKey:VK_ESCAPE),
  48.    (Name:'ESCAPE';          VKey:VK_ESCAPE),
  49.    (Name:'F1';              VKey:VK_F1),
  50.    (Name:'F10';             VKey:VK_F10),
  51.    (Name:'F11';             VKey:VK_F11),
  52.    (Name:'F12';             VKey:VK_F12),
  53.    (Name:'F13';             VKey:VK_F13),
  54.    (Name:'F14';             VKey:VK_F14),
  55.    (Name:'F15';             VKey:VK_F15),
  56.    (Name:'F16';             VKey:VK_F16),
  57.    (Name:'F2';              VKey:VK_F2),
  58.    (Name:'F3';              VKey:VK_F3),
  59.    (Name:'F4';              VKey:VK_F4),
  60.    (Name:'F5';              VKey:VK_F5),
  61.    (Name:'F6';              VKey:VK_F6),
  62.    (Name:'F7';              VKey:VK_F7),
  63.    (Name:'F8';              VKey:VK_F8),
  64.    (Name:'F9';              VKey:VK_F9),
  65.    (Name:'HELP';            VKey:VK_HELP),
  66.    (Name:'HOME';            VKey:VK_HOME),
  67.    (Name:'INS';             VKey:VK_INSERT),
  68.    (Name:'LEFT';            VKey:VK_LEFT),
  69.    (Name:'NUMLOCK';         VKey:VK_NUMLOCK),
  70.    (Name:'PGDN';            VKey:VK_NEXT),
  71.    (Name:'PGUP';            VKey:VK_PRIOR),
  72.    (Name:'PRTSC';           VKey:VK_PRINT),
  73.    (Name:'RIGHT';           VKey:VK_RIGHT),
  74.    (Name:'SCROLLLOCK';      VKey:VK_SCROLL),
  75.    (Name:'TAB';             VKey:VK_TAB),
  76.    (Name:'UP';              VKey:VK_UP)
  77.   );
  78.   {Extra VK constants missing from Delphi's Windows API interface}
  79.   VK_NULL=0;
  80.   VK_SemiColon=186;
  81.   VK_Equal=187;
  82.   VK_Comma=188;
  83.   VK_Minus=189;
  84.   VK_Period=190;
  85.   VK_Slash=191;
  86.   VK_BackQuote=192;
  87.   VK_LeftBracket=219;
  88.   VK_BackSlash=220;
  89.   VK_RightBracket=221;
  90.   VK_Quote=222;
  91.   VK_Last=VK_Quote;
  92.   ExtendedVKeys : set of byte =
  93.   [VK_Up,
  94.    VK_Down,
  95.    VK_Left,
  96.    VK_Right,
  97.    VK_Home,
  98.    VK_End,
  99.    VK_Prior,  {PgUp}
  100.    VK_Next,   {PgDn}
  101.    VK_Insert,
  102.    VK_Delete];
  103. const
  104.   INVALIDKEY = $FFFF {Unsigned -1};
  105.   VKKEYSCANSHIFTON = $01;
  106.   VKKEYSCANCTRLON = $02;
  107.   VKKEYSCANALTON = $04;
  108.   UNITNAME = 'SendKeys';
  109. var
  110.   UsingParens, ShiftDown, ControlDown, AltDown, FoundClose : Boolean;
  111.   PosSpace : Byte;
  112.   I, L : Integer;
  113.   NumTimes, MKey : Word;
  114.   KeyString : String[20];
  115. procedure DisplayMessage(Message : PChar);
  116. begin
  117.   MessageBox(0,Message,UNITNAME,0);
  118. end;
  119. function BitSet(BitTable, BitMask : Byte) : Boolean;
  120. begin
  121.   Result:=ByteBool(BitTable and BitMask);
  122. end;
  123. procedure SetBit(var BitTable : Byte; BitMask : Byte);
  124. begin
  125.   BitTable:=BitTable or Bitmask;
  126. end;
  127. Procedure KeyboardEvent(VKey, ScanCode : Byte; Flags : Longint);
  128. var
  129.   KeyboardMsg : TMsg;
  130. begin
  131.   keybd_event(VKey, ScanCode, Flags,0);
  132.   If (Wait) then While (PeekMessage(KeyboardMsg,0,WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) do begin
  133.     TranslateMessage(KeyboardMsg);
  134.     DispatchMessage(KeyboardMsg);
  135.   end;
  136. end;
  137. Procedure SendKeyDown(VKey: Byte; NumTimes : Word; GenUpMsg : Boolean);
  138. var
  139.   Cnt : Word;
  140.   ScanCode : Byte;
  141.   NumState : Boolean;
  142.   KeyBoardState : TKeyboardState;
  143. begin
  144.   If (VKey=VK_NUMLOCK) then begin
  145.     NumState:=ByteBool(GetKeyState(VK_NUMLOCK) and 1);
  146.     GetKeyBoardState(KeyBoardState);
  147.     If NumState then KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] and not 1)
  148.     else KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] or 1);
  149.     SetKeyBoardState(KeyBoardState);
  150.     exit;
  151.   end;
  152.   ScanCode:=Lo(MapVirtualKey(VKey,0));
  153.   For Cnt:=1 to NumTimes do
  154.     If (VKey in ExtendedVKeys)then begin
  155.       KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY);
  156.       If (GenUpMsg) then
  157.         KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)
  158.     end else begin
  159.       KeyboardEvent(VKey, ScanCode, 0);
  160.       If (GenUpMsg) then KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
  161.     end;
  162. end;
  163. Procedure SendKeyUp(VKey: Byte);
  164. var
  165.   ScanCode : Byte;
  166. begin
  167.   ScanCode:=Lo(MapVirtualKey(VKey,0));
  168.   If (VKey in ExtendedVKeys)then
  169.     KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)
  170.   else KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
  171. end;
  172. Procedure SendKey(MKey: Word; NumTimes : Word; GenDownMsg : Boolean);
  173. begin
  174.   If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyDown(VK_SHIFT,1,False);
  175.   If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyDown(VK_CONTROL,1,False);
  176.   If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyDown(VK_MENU,1,False);
  177.   SendKeyDown(Lo(MKey), NumTimes, GenDownMsg);
  178.   If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyUp(VK_SHIFT);
  179.   If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyUp(VK_CONTROL);
  180.   If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyUp(VK_MENU);
  181. end;
  182. {Implements a simple binary search to locate special key name strings}
  183. Function StringToVKey(KeyString : ShortString) : Word;
  184. var
  185.   Found, Collided : Boolean;
  186.   Bottom, Top, Middle : Byte;
  187. begin
  188.   Result:=INVALIDKEY;
  189.   Bottom:=1;
  190.   Top:=MaxSendKeyRecs;
  191.   Found:=false;
  192.   Middle:=(Bottom+Top) div 2;
  193.   Repeat
  194.     Collided:=((Bottom=Middle) or (Top=Middle));
  195.     If (KeyString=SendKeyRecs[Middle].Name) then begin
  196.        Found:=True;
  197.        Result:=SendKeyRecs[Middle].VKey;
  198.     end else begin
  199.        If (KeyString>SendKeyRecs[Middle].Name) then Bottom:=Middle
  200.        else Top:=Middle;
  201.        Middle:=(Succ(Bottom+Top)) div 2;
  202.     end;
  203.   Until (Found or Collided);
  204.   If (Result=INVALIDKEY) then DisplayMessage('Invalid Key Name');
  205. end;
  206. procedure PopUpShiftKeys;
  207. begin
  208.   If (not UsingParens) then begin
  209.     If ShiftDown then SendKeyUp(VK_SHIFT);
  210.     If ControlDown then SendKeyUp(VK_CONTROL);
  211.     If AltDown then SendKeyUp(VK_MENU);
  212.     ShiftDown:=false;
  213.     ControlDown:=false;
  214.     AltDown:=false;
  215.   end;
  216. end;
  217. begin
  218.   AllocationSize:=MaxInt;
  219.   Result:=false;
  220.   UsingParens:=false;
  221.   ShiftDown:=false;
  222.   ControlDown:=false;
  223.   AltDown:=false;
  224.   I:=0;
  225.   L:=StrLen(SendKeysString);
  226.   If (L>AllocationSize) then L:=AllocationSize;
  227.   If (L=0then Exit;
  228.   While (I<L) do begin
  229.     case SendKeysString[I] of
  230.     '(' : begin
  231.             UsingParens:=True;
  232.             Inc(I);
  233.           end;
  234.     ')' : begin
  235.             UsingParens:=False;
  236.             PopUpShiftKeys;
  237.             Inc(I);
  238.           end;
  239.     '%' : begin
  240.              AltDown:=True;
  241.              SendKeyDown(VK_MENU,1,False);
  242.              Inc(I);
  243.           end;
  244.     '+' :  begin
  245.              ShiftDown:=True;
  246.              SendKeyDown(VK_SHIFT,1,False);
  247.              Inc(I);
  248.            end;
  249.     '^' :  begin
  250.              ControlDown:=True;
  251.              SendKeyDown(VK_CONTROL,1,False);
  252.              Inc(I);
  253.            end;
  254.     '{' : begin
  255.             NumTimes:=1;
  256.             If (SendKeysString[Succ(I)]='{'then begin
  257.               MKey:=VK_LEFTBRACKET;
  258.               SetBit(Wbytes(MKey)[1],VKKEYSCANSHIFTON);
  259.               SendKey(MKey,1,True);
  260.               PopUpShiftKeys;
  261.               Inc(I,3);
  262.               Continue;
  263.             end;
  264.             KeyString:='';
  265.             FoundClose:=False;
  266.             While (I<=L) do begin
  267.               Inc(I);
  268.               If (SendKeysString[I]='}'then begin
  269.                 FoundClose:=True;
  270.                 Inc(I);
  271.                 Break;
  272.               end;
  273.               KeyString:=KeyString+Upcase(SendKeysString[I]);
  274.             end;
  275.             If (Not FoundClose) then begin
  276.                DisplayMessage('No Close');
  277.                Exit;
  278.             end;
  279.             If (SendKeysString[I]='}'then begin
  280.               MKey:=VK_RIGHTBRACKET;
  281.               SetBit(Wbytes(MKey)[1],VKKEYSCANSHIFTON);
  282.               SendKey(MKey,1,True);
  283.               PopUpShiftKeys;
  284.               Inc(I);
  285.               Continue;
  286.             end;
  287.             PosSpace:=Pos(' ',KeyString);
  288.             If (PosSpace<>0then begin
  289.                NumTimes:=StrToInt(Copy(KeyString,Succ(PosSpace),Length(KeyString)-PosSpace));
  290.                KeyString:=Copy(KeyString,1,Pred(PosSpace));
  291.             end;
  292.             If (Length(KeyString)=1then MKey:=vkKeyScan(KeyString[1])
  293.             else MKey:=StringToVKey(KeyString);
  294.             If (MKey<>INVALIDKEY) then begin
  295.               SendKey(MKey,NumTimes,True);
  296.               PopUpShiftKeys;
  297.               Continue;
  298.             end;
  299.           end;
  300.     '~' : begin
  301.             SendKeyDown(VK_RETURN,1,True);
  302.             PopUpShiftKeys;
  303.             Inc(I);
  304.           end;
  305.     else  begin
  306.              MKey:=vkKeyScan(SendKeysString[I]);
  307.              If (MKey<>INVALIDKEY) then begin
  308.                SendKey(MKey,1,True);
  309.                PopUpShiftKeys;
  310.              end else DisplayMessage('Invalid KeyName');
  311.              Inc(I);
  312.           end;
  313.     end;
  314.   end;
  315.   Result:=true;
  316.   PopUpShiftKeys;
  317. end;
  318. {AppActivate
  319. This is used to set the current input focus to a given window using its
  320. name.  This is especially useful for ensuring a window is active before
  321. sending it input messages using the SendKeys function.  You can specify
  322. a window's name in its entirety, or only portion of it, beginning from
  323. the left.
  324. }
  325. var
  326.   WindowHandle : HWND;
  327. function EnumWindowsProc(WHandle: HWND; lParam: LPARAM): BOOL; export; stdcall;
  328. const
  329.   MAX_WINDOW_NAME_LEN = 80;
  330. var
  331.   WindowName : array[0..MAX_WINDOW_NAME_LEN] of char;
  332. begin
  333.   {Can't test GetWindowText's return value since some windows don't have a title}
  334.   GetWindowText(WHandle,WindowName,MAX_WINDOW_NAME_LEN);
  335.   Result := (StrLIComp(WindowName,PChar(lParam), StrLen(PChar(lParam))) <> 0);
  336.   If (not Result) then WindowHandle:=WHandle;
  337. end;
  338. function AppActivate(WindowName : PChar) : boolean;
  339. begin
  340.   try
  341.     Result:=true;
  342.     WindowHandle:=FindWindow(nil,WindowName);
  343.     If (WindowHandle=0then EnumWindows(@EnumWindowsProc,Integer(PChar(WindowName)));
  344.     If (WindowHandle<>0then begin
  345.       SendMessage(WindowHandle, WM_SYSCOMMAND, SC_HOTKEY, WindowHandle);
  346.       SendMessage(WindowHandle, WM_SYSCOMMAND, SC_RESTORE, WindowHandle);
  347.     end else Result:=false;
  348.   except
  349.     on Exception do Result:=false;
  350.   end;
  351. end;
  352. end.   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值