Pergunta

I need to send several virtual keys (VK_RETURN) from my delphi application (myapp.exe) into another application (target.exe). Eg : Send VK_RETURN twice , from myapp.exe , into target.exe

The OS that I use are Windows 7 64 bit and Windows XP.

I read : How to send an "ENTER" key press to another application? , Send Ctrl+Key to a 3rd Party Application (did not work for me) and other previous asked question. But still I'm getting confused.

How to set the focus to the target application ?

How to send the virtual keys to the targeted application ?

Simple example : I want to send VK_RETURN twice into notepad.exe or calc.exe (already loaded) or any other program from my delphi application. How to do that ?

The simplest way to do this in Delphi 2010, please...

PS : I tried SndKey32.pass from http://delphi.about.com/od/adptips2004/a/bltip1104_3.htm And got error : [DCC Error] SndKey32.pas(420): E2010 Incompatible types: 'Char' and 'AnsiChar'

  If (Length(KeyString)=1) then MKey:=vkKeyScan(KeyString[1])
Foi útil?

Solução

If your target application isn't the foreground window, you need to use PostMessage to send keystrokes to its window handle. You can get that window handle using FindWindow. The code below sends the Enter key to a the text area in a running instance of Notepad (note it uses an additional FindWindowEx to locate the memo area first). It was tested using both Delphi 2007 and Delphi XE4 (32-bit target) on Windows 7 64.

uses Windows;
    
procedure TForm1.Button1Click(Sender: TObject);
var
  NpWnd, NpEdit: HWnd;
begin
  NpWnd := FindWindow('Notepad', nil);
  if NpWnd <> 0 then
  begin
    NpEdit := FindWindowEx(NpWnd, 0, 'Edit', nil);
    if NpEdit <> 0 then
    begin
      PostMessage(NpEdit, WM_KEYDOWN, VK_RETURN, 0);
      PostMessage(NpEdit, WM_KEYUP, VK_RETURN, 0); 
    end;
  end;
end;

To find the window by title (caption) instead, you can just use the second parameter to FindWindow. This finds a new instance of Notepad with the default 'Untitled' file open:

NpWnd := FindWindow(nil, 'Untitled - Notepad');

Note that this requires as exact match on the window title. An extra space before or after the -, for instance, will cause the match to fail and the window handle to not be retrieved.

You can use both the window class and title if you have multiple instances running. To find the copy of Notepad running with Readme.txt loaded, you would use

NpWnd := FindWindow('Notepad', 'Readme.txt - Notepad');

To find other applications, you'll need to use something like WinSpy or WinSight to find the window class names. (There are others also, such as Winspector or WinDowse (both of which are written in Delphi).)

Your comment mentions Calculator; according to Winspector, the Calculator main window is in a window class called CalcFrame on Windows 7, and the area the numbers are displayed in is a Static window (meaning it doesn't seem to receive keystrokes directly). The buttons are simply called Button, so you'd have to loop through them using EnumChildWindows looking for the individual buttons to identify them in order to obtain their handles.

(How to enumerate child windows is a separate question; you can probably find an example by searching here or via Google. If you can't, post a new, separate question about that and we can try to get you an answer.)

Here's a quick example of sending keys to Calculator after finding it by window class. It doesn't do anything useful, because it needs some time spent to identify different buttons and the keys that each responds to (and the proper combination of messages). This code simply sends 11Numpad+22 to the calculator window (a quick test showed that they were properly received and displayed, and that's about all the time I wanted to spend on the process).

uses Windows;

procedure TForm1.Button1Click(Sender: TObject);
var
  NpWnd: HWnd;
begin
  NpWnd := FindWindow('CalcFrame',  nil);
  if NpWnd <> 0 then
  begin
    PostMessage(NpWnd, WM_KEYDOWN, VK_NUMPAD1, 0);
    PostMessage(NpWnd, WM_KEYDOWN, VK_ADD, 0);
    PostMessage(NpWnd, WM_KEYDOWN, VK_NUMPAD2, 0);
  end;
end;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top