sndkey32.pas
上传用户:wang_niyan
上传日期:2022-05-07
资源大小:313k
文件大小:14k
源码类别:

编辑器/阅读器

开发平台:

Delphi

  1. (*
  2. SendKeys routine for 32-bit Delphi.
  3. Written by Ken Henderson
  4. Copyright (c) 1995 Ken Henderson
  5. This unit includes two routines that simulate popular Visual Basic
  6. routines: Sendkeys and AppActivate.  SendKeys takes a PChar
  7. as its first parameter and a boolean as its second, like so:
  8. SendKeys('KeyString', Wait);
  9. where KeyString is a string of key names and modifiers that you want
  10. to send to the current input focus and Wait is a boolean variable or value
  11. that indicates whether SendKeys should wait for each key message to be
  12. processed before proceeding.  See the table below for more information.
  13. AppActivate also takes a PChar as its only parameter, like so:
  14. AppActivate('WindowName');
  15. where WindowName is the name of the window that you want to make the
  16. current input focus.
  17. SendKeys supports the Visual Basic SendKeys syntax, as documented below.
  18. Supported modifiers:
  19. + = Shift
  20. ^ = Control
  21. % = Alt
  22. Surround sequences of characters or key names with parentheses in order to
  23. modify them as a group.  For example, '+abc' shifts only 'a', while '+(abc)' shifts
  24. all three characters.
  25. Supported special characters
  26. ~ = Enter
  27. ( = Begin modifier group (see above)
  28. ) = End modifier group (see above)
  29. { = Begin key name text (see below)
  30. } = End key name text (see below)
  31. Supported characters:
  32. Any character that can be typed is supported.  Surround the modifier keys
  33. listed above with braces in order to send as normal text.
  34. Supported key names (surround these with braces):
  35. BKSP, BS, BACKSPACE
  36. BREAK
  37. CAPSLOCK
  38. CLEAR
  39. DEL
  40. DELETE
  41. DOWN
  42. END
  43. ENTER
  44. ESC
  45. ESCAPE
  46. F1
  47. F2
  48. F3
  49. F4
  50. F5
  51. F6
  52. F7
  53. F8
  54. F9
  55. F10
  56. F11
  57. F12
  58. F13
  59. F14
  60. F15
  61. F16
  62. HELP
  63. HOME
  64. INS
  65. LEFT
  66. NUMLOCK
  67. PGDN
  68. PGUP
  69. PRTSC
  70. RIGHT
  71. SCROLLLOCK
  72. TAB
  73. UP
  74. Follow the keyname with a space and a number to send the specified key a
  75. given number of times (e.g., {left 6}).
  76. *)
  77. unit sndkey32;
  78. interface
  79. Uses SysUtils, Windows, Messages;
  80. Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;
  81. function AppActivate(WindowName : PChar) : boolean; overload;
  82. function AppActivate(WindowHandle : HWND) : boolean; overload;
  83. {Buffer for working with PChar's}
  84. const
  85.   WorkBufLen = 40;
  86. var
  87.   WorkBuf : array[0..WorkBufLen] of Char;
  88. implementation
  89. type
  90.   THKeys = array[0..pred(MaxLongInt)] of byte;
  91. var
  92.   AllocationSize : integer;
  93. (*
  94. Converts a string of characters and key names to keyboard events and
  95. passes them to Windows.
  96. Example syntax:
  97. SendKeys('abc123{left}{left}{left}def{end}456{left 6}ghi{end}789', True);
  98. *)
  99. Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;
  100. type
  101.   WBytes = array[0..pred(SizeOf(Word))] of Byte;
  102.   TSendKey = record
  103.     Name : ShortString;
  104.     VKey : Byte;
  105.   end;
  106. const
  107.   {Array of keys that SendKeys recognizes.
  108.   If you add to this list, you must be sure to keep it sorted alphabetically
  109.   by Name because a binary search routine is used to scan it.}
  110.   MaxSendKeyRecs = 41;
  111.   SendKeyRecs : array[1..MaxSendKeyRecs] of TSendKey =
  112.   (
  113.    (Name:'BACKSPACE';       VKey:VK_BACK),
  114.    (Name:'BKSP';            VKey:VK_BACK),
  115.    (Name:'BREAK';           VKey:VK_CANCEL),
  116.    (Name:'BS';              VKey:VK_BACK),
  117.    (Name:'CAPSLOCK';        VKey:VK_CAPITAL),
  118.    (Name:'CLEAR';           VKey:VK_CLEAR),
  119.    (Name:'DEL';             VKey:VK_DELETE),
  120.    (Name:'DELETE';          VKey:VK_DELETE),
  121.    (Name:'DOWN';            VKey:VK_DOWN),
  122.    (Name:'END';             VKey:VK_END),
  123.    (Name:'ENTER';           VKey:VK_RETURN),
  124.    (Name:'ESC';             VKey:VK_ESCAPE),
  125.    (Name:'ESCAPE';          VKey:VK_ESCAPE),
  126.    (Name:'F1';              VKey:VK_F1),
  127.    (Name:'F10';             VKey:VK_F10),
  128.    (Name:'F11';             VKey:VK_F11),
  129.    (Name:'F12';             VKey:VK_F12),
  130.    (Name:'F13';             VKey:VK_F13),
  131.    (Name:'F14';             VKey:VK_F14),
  132.    (Name:'F15';             VKey:VK_F15),
  133.    (Name:'F16';             VKey:VK_F16),
  134.    (Name:'F2';              VKey:VK_F2),
  135.    (Name:'F3';              VKey:VK_F3),
  136.    (Name:'F4';              VKey:VK_F4),
  137.    (Name:'F5';              VKey:VK_F5),
  138.    (Name:'F6';              VKey:VK_F6),
  139.    (Name:'F7';              VKey:VK_F7),
  140.    (Name:'F8';              VKey:VK_F8),
  141.    (Name:'F9';              VKey:VK_F9),
  142.    (Name:'HELP';            VKey:VK_HELP),
  143.    (Name:'HOME';            VKey:VK_HOME),
  144.    (Name:'INS';             VKey:VK_INSERT),
  145.    (Name:'LEFT';            VKey:VK_LEFT),
  146.    (Name:'NUMLOCK';         VKey:VK_NUMLOCK),
  147.    (Name:'PGDN';            VKey:VK_NEXT),
  148.    (Name:'PGUP';            VKey:VK_PRIOR),
  149.    (Name:'PRTSC';           VKey:VK_PRINT),
  150.    (Name:'RIGHT';           VKey:VK_RIGHT),
  151.    (Name:'SCROLLLOCK';      VKey:VK_SCROLL),
  152.    (Name:'TAB';             VKey:VK_TAB),
  153.    (Name:'UP';              VKey:VK_UP)
  154.   );
  155.   {Extra VK constants missing from Delphi's Windows API interface}
  156.   VK_NULL=0;
  157.   VK_SemiColon=186;
  158.   VK_Equal=187;
  159.   VK_Comma=188;
  160.   VK_Minus=189;
  161.   VK_Period=190;
  162.   VK_Slash=191;
  163.   VK_BackQuote=192;
  164.   VK_LeftBracket=219;
  165.   VK_BackSlash=220;
  166.   VK_RightBracket=221;
  167.   VK_Quote=222;
  168.   VK_Last=VK_Quote;
  169.   ExtendedVKeys : set of byte =
  170.   [VK_Up,
  171.    VK_Down,
  172.    VK_Left,
  173.    VK_Right,
  174.    VK_Home,
  175.    VK_End,
  176.    VK_Prior,  {PgUp}
  177.    VK_Next,   {PgDn}
  178.    VK_Insert,
  179.    VK_Delete];
  180. const
  181.   INVALIDKEY = $FFFF {Unsigned -1};
  182.   VKKEYSCANSHIFTON = $01;
  183.   VKKEYSCANCTRLON = $02;
  184.   VKKEYSCANALTON = $04;
  185.   UNITNAME = 'SendKeys';
  186. var
  187.   UsingParens, ShiftDown, ControlDown, AltDown, FoundClose : Boolean;
  188.   PosSpace : Byte;
  189.   I, L : Integer;
  190.   NumTimes, MKey : Word;
  191.   KeyString : String[20];
  192. procedure DisplayMessage(Message : PChar);
  193. begin
  194.   MessageBox(0,Message,UNITNAME,0);
  195. end;
  196. function BitSet(BitTable, BitMask : Byte) : Boolean;
  197. begin
  198.   Result:=ByteBool(BitTable and BitMask);
  199. end;
  200. procedure SetBit(var BitTable : Byte; BitMask : Byte);
  201. begin
  202.   BitTable:=BitTable or Bitmask;
  203. end;
  204. Procedure KeyboardEvent(VKey, ScanCode : Byte; Flags : Longint);
  205. var
  206.   KeyboardMsg : TMsg;
  207. begin
  208.   keybd_event(VKey, ScanCode, Flags,0);
  209.   If (Wait) then While (PeekMessage(KeyboardMsg,0,WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) do begin
  210.     TranslateMessage(KeyboardMsg);
  211.     DispatchMessage(KeyboardMsg);
  212.   end;
  213. end;
  214. Procedure SendKeyDown(VKey: Byte; NumTimes : Word; GenUpMsg : Boolean);
  215. var
  216.   Cnt : Word;
  217.   ScanCode : Byte;
  218.   NumState : Boolean;
  219.   KeyBoardState : TKeyboardState;
  220. begin
  221.   If (VKey=VK_NUMLOCK) then begin
  222.     NumState:=ByteBool(GetKeyState(VK_NUMLOCK) and 1);
  223.     GetKeyBoardState(KeyBoardState);
  224.     If NumState then KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] and not 1)
  225.     else KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] or 1);
  226.     SetKeyBoardState(KeyBoardState);
  227.     exit;
  228.   end;
  229.   ScanCode:=Lo(MapVirtualKey(VKey,0));
  230.   For Cnt:=1 to NumTimes do
  231.     If (VKey in ExtendedVKeys)then begin
  232.       KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY);
  233.       If (GenUpMsg) then
  234.         KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)
  235.     end else begin
  236.       KeyboardEvent(VKey, ScanCode, 0);
  237.       If (GenUpMsg) then KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
  238.     end;
  239. end;
  240. Procedure SendKeyUp(VKey: Byte);
  241. var
  242.   ScanCode : Byte;
  243. begin
  244.   ScanCode:=Lo(MapVirtualKey(VKey,0));
  245.   If (VKey in ExtendedVKeys)then
  246.     KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)
  247.   else KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
  248. end;
  249. Procedure SendKey(MKey: Word; NumTimes : Word; GenDownMsg : Boolean);
  250. begin
  251.   If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyDown(VK_SHIFT,1,False);
  252.   If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyDown(VK_CONTROL,1,False);
  253.   If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyDown(VK_MENU,1,False);
  254.   SendKeyDown(Lo(MKey), NumTimes, GenDownMsg);
  255.   If (BitSet(Hi(MKey),VKKEYSCANSHIFTON)) then SendKeyUp(VK_SHIFT);
  256.   If (BitSet(Hi(MKey),VKKEYSCANCTRLON)) then SendKeyUp(VK_CONTROL);
  257.   If (BitSet(Hi(MKey),VKKEYSCANALTON)) then SendKeyUp(VK_MENU);
  258. end;
  259. {Implements a simple binary search to locate special key name strings}
  260. Function StringToVKey(KeyString : ShortString) : Word;
  261. var
  262.   Found, Collided : Boolean;
  263.   Bottom, Top, Middle : Byte;
  264. begin
  265.   Result:=INVALIDKEY;
  266.   Bottom:=1;
  267.   Top:=MaxSendKeyRecs;
  268.   Found:=false;
  269.   Middle:=(Bottom+Top) div 2;
  270.   Repeat
  271.     Collided:=((Bottom=Middle) or (Top=Middle));
  272.     If (KeyString=SendKeyRecs[Middle].Name) then begin
  273.        Found:=True;
  274.        Result:=SendKeyRecs[Middle].VKey;
  275.     end else begin
  276.        If (KeyString>SendKeyRecs[Middle].Name) then Bottom:=Middle
  277.        else Top:=Middle;
  278.        Middle:=(Succ(Bottom+Top)) div 2;
  279.     end;
  280.   Until (Found or Collided);
  281.   If (Result=INVALIDKEY) then //DisplayMessage('Invalid Key Name');
  282. end;
  283. procedure PopUpShiftKeys;
  284. begin
  285.   If (not UsingParens) then begin
  286.     If ShiftDown then SendKeyUp(VK_SHIFT);
  287.     If ControlDown then SendKeyUp(VK_CONTROL);
  288.     If AltDown then SendKeyUp(VK_MENU);
  289.     ShiftDown:=false;
  290.     ControlDown:=false;
  291.     AltDown:=false;
  292.   end;
  293. end;
  294. begin
  295.   AllocationSize:=MaxInt;
  296.   Result:=false;
  297.   UsingParens:=false;
  298.   ShiftDown:=false;
  299.   ControlDown:=false;
  300.   AltDown:=false;
  301.   I:=0;
  302.   L:=StrLen(SendKeysString);
  303.   If (L>AllocationSize) then L:=AllocationSize;
  304.   If (L=0) then Exit;
  305.   While (I<L) do begin
  306.     case SendKeysString[I] of
  307.     '(' : begin
  308.             UsingParens:=True;
  309.             Inc(I);
  310.           end;
  311.     ')' : begin
  312.             UsingParens:=False;
  313.             PopUpShiftKeys;
  314.             Inc(I);
  315.           end;
  316.     '%' : begin
  317.              AltDown:=True;
  318.              SendKeyDown(VK_MENU,1,False);
  319.              Inc(I);
  320.           end;
  321.     '+' :  begin
  322.              ShiftDown:=True;
  323.              SendKeyDown(VK_SHIFT,1,False);
  324.              Inc(I);
  325.            end;
  326.     '^' :  begin
  327.              ControlDown:=True;
  328.              SendKeyDown(VK_CONTROL,1,False);
  329.              Inc(I);
  330.            end;
  331.     '{' : begin
  332.             NumTimes:=1;
  333.             If (SendKeysString[Succ(I)]='{') then begin
  334.               MKey:=VK_LEFTBRACKET;
  335.               SetBit(Wbytes(MKey)[1],VKKEYSCANSHIFTON);
  336.               SendKey(MKey,1,True);
  337.               PopUpShiftKeys;
  338.               Inc(I,3);
  339.               Continue;
  340.             end;
  341.             KeyString:='';
  342.             FoundClose:=False;
  343.             While (I<=L) do begin
  344.               Inc(I);
  345.               If (SendKeysString[I]='}') then begin
  346.                 FoundClose:=True;
  347.                 Inc(I);
  348.                 Break;
  349.               end;
  350.               KeyString:=KeyString+Upcase(SendKeysString[I]);
  351.             end;
  352.             If (Not FoundClose) then begin
  353.                DisplayMessage('No Close');
  354.                Exit;
  355.             end;
  356.             If (SendKeysString[I]='}') then begin
  357.               MKey:=VK_RIGHTBRACKET;
  358.               SetBit(Wbytes(MKey)[1],VKKEYSCANSHIFTON);
  359.               SendKey(MKey,1,True);
  360.               PopUpShiftKeys;
  361.               Inc(I);
  362.               Continue;
  363.             end;
  364.             PosSpace:=Pos(' ',KeyString);
  365.             If (PosSpace<>0) then begin
  366.                NumTimes:=StrToInt(Copy(KeyString,Succ(PosSpace),Length(KeyString)-PosSpace));
  367.                KeyString:=Copy(KeyString,1,Pred(PosSpace));
  368.             end;
  369.             If (Length(KeyString)=1) then MKey:=vkKeyScanA(KeyString[1])
  370.             else MKey:=StringToVKey(KeyString);
  371.             If (MKey<>INVALIDKEY) then begin
  372.               SendKey(MKey,NumTimes,True);
  373.               PopUpShiftKeys;
  374.               Continue;
  375.             end;
  376.           end;
  377.     '~' : begin
  378.             SendKeyDown(VK_RETURN,1,True);
  379.             PopUpShiftKeys;
  380.             Inc(I);
  381.           end;
  382.     else  begin
  383.              MKey:=vkKeyScan(SendKeysString[I]);
  384.              If (MKey<>INVALIDKEY) then begin
  385.                SendKey(MKey,1,True);
  386.                PopUpShiftKeys;
  387.              end else ;//DisplayMessage('Invalid KeyName');
  388.              Inc(I);
  389.           end;
  390.     end;
  391.   end;
  392.   Result:=true;
  393.   PopUpShiftKeys;
  394. end;
  395. {AppActivate
  396. This is used to set the current input focus to a given window using its
  397. name.  This is especially useful for ensuring a window is active before
  398. sending it input messages using the SendKeys function.  You can specify
  399. a window's name in its entirety, or only portion of it, beginning from
  400. the left.
  401. }                
  402. var
  403.   WindowHandle: HWND;
  404. function EnumWindowsProc(WHandle: HWND; lParam: LPARAM): BOOL; export; stdcall;
  405. var
  406.   WindowName: array[0..MAX_PATH] of Char;
  407. begin
  408.   {Can't test GetWindowText's return value since some windows don't have a title}
  409.   GetWindowText(WHandle, WindowName, MAX_PATH);
  410.   Result := (StrLIComp(WindowName,PChar(lParam), StrLen(PChar(lParam))) <> 0);
  411.   if not Result then
  412.     WindowHandle := WHandle;
  413. end;
  414. function AppActivate(WindowHandle: HWND): Boolean; overload;
  415. begin
  416.   try
  417.     SendMessage(WindowHandle, WM_SYSCOMMAND, SC_HOTKEY, WindowHandle);
  418.     SendMessage(WindowHandle, WM_SYSCOMMAND, SC_RESTORE, WindowHandle);
  419.     Result := SetForegroundWindow(WindowHandle);
  420.   except
  421.     on Exception do
  422.       Result := False;
  423.   end;
  424. end;
  425. function AppActivate(WindowName: PChar): Boolean; overload;
  426. begin
  427.   try
  428.     Result := True;
  429.     WindowHandle:=FindWindow(nil, WindowName);
  430.     if (WindowHandle = 0) then
  431.       EnumWindows(@EnumWindowsProc, Integer(PChar(WindowName)));
  432.     if (WindowHandle <> 0) then
  433.     begin
  434.       SendMessage(WindowHandle, WM_SYSCOMMAND, SC_HOTKEY, WindowHandle);
  435.       SendMessage(WindowHandle, WM_SYSCOMMAND, SC_RESTORE, WindowHandle);
  436.       SetForegroundWindow(WindowHandle);
  437.     end else
  438.       Result := False;
  439.   except
  440.     on Exception do
  441.       Result := False;
  442.   end;
  443. end;
  444. end.