[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Send keyboard strokes to another application in the background

Posted on 2011-05-03
5
Medium Priority
?
1,873 Views
Last Modified: 2013-12-09
I am trying to send a Ctrl-S to another application running in the background called Bridge.  I read the other postings on this topic but I cannot make it work.  Here is my code:

procedure TForm1.Button1Click(Sender: TObject);
var
  Hx: THandle;
  P: array[0..256] of Char;
begin

  Hx := FindWindow(nil, 'Untitled - Bridge');
  GetClassName(Hx, P, SizeOf(P));

  Hx := FindWindow(P,nil);
  postmessage(Hx, wm_keydown, VK_CONTROL, 0);       //Send Ctrl down
  postmessage(Hx, wm_keydown, VkKeyScan('s'), 0);   //Send 's' down
  postmessage(Hx, wm_keyup, VkKeyScan('s'), 0);     //Send 's' up
  postmessage(Hx, wm_keyup, VK_CONTROL, 0);         ////Send Ctrl up
end;

I am using the classname because of the scenario that the user must have saved the document in Bridge with a different name other than "Untitled".

Thank you.
0
Comment
Question by:aac111
  • 3
5 Comments
 
LVL 23

Accepted Solution

by:
Ferruccio Accalai earned 1400 total points
ID: 35691207
You could try to use this approach.

First search for the window by title (If you don't know the title how can you get the correct window?) and then send the keystrokes by keybd_event

function FindWindowByTitle(WindowTitle: string): Hwnd;
var
  NextHandle: Hwnd;
  NextTitle: array [0..260] of char;
begin
  // Get the first window
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    // retrieve its text
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      Result := NextHandle;
      Exit;
    end
    else
      // Get the next window
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  hx: Hwnd;
begin
  hx := FindWindowByTitle('Untitled');
  if hx <> 0 then
  begin
    SetForegroundWindow(hx);
    keybd_event(VK_CONTROL, 1, 0, 0);
    keybd_event(VkKeyScan('s'), 1, 0, 0);
    keybd_event(VkKeyScan('s'), 1, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, 1, KEYEVENTF_KEYUP, 0);
  end;
end;
0
 
LVL 21

Assisted Solution

by:developmentguru
developmentguru earned 600 total points
ID: 35695097
You will need to change how you call these windows API calls you are using.  I have done a lot of windows api programming in Delphi and I have always had to use the address of the character buffer.  Depending on the version of Delphi you are using, you may need to be careful to use the correct type of char for the array (old, 1 byte, char vs wide char).  You should also make sure to check the results of each API call to see if it worked.  Here are the links on the API functions...

http://msdn.microsoft.com/en-us/library/ms633582(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/ms633499(v=vs.85).aspx
procedure TForm1.Button1Click(Sender: TObject);
var 
  Hx: THandle;
  P: array[0..256] of Char;
begin

  Hx := FindWindow(nil, 'Untitled - Bridge');
  if hx <> 0 then
    begin
      if GetClassName(Hx, @P, SizeOf(P)) <> 0 then
        begin

          Hx := FindWindow(@P,nil);
          postmessage(Hx, wm_keydown, VK_CONTROL, 0);       //Send Ctrl down
          postmessage(Hx, wm_keydown, VkKeyScan('s'), 0);   //Send 's' down
          postmessage(Hx, wm_keyup, VkKeyScan('s'), 0);     //Send 's' up
          postmessage(Hx, wm_keyup, VK_CONTROL, 0);         ////Send Ctrl up
        end;
    end;
end;

Open in new window

0
 

Author Comment

by:aac111
ID: 35703247
@Ferruccio68:

Do I need to setforegroundwindow?  I need to be able to send the keystrokes without bringing the window to the foreground.

Thank you.
0
 
LVL 23

Expert Comment

by:Ferruccio Accalai
ID: 35704413
The keyboard event is sent like if a key on the phisical keyboard is pressed, and to get it work on the desidered control it must be focused. That's why the window must be the topmost one
0
 
LVL 23

Assisted Solution

by:Ferruccio Accalai
Ferruccio Accalai earned 1400 total points
ID: 35704422
Submited too early

Anyway, ones you've got the handle, you could still use it combined with postmessage (or sendmessage)

 hx := FindWindowByTitle('Untitled');
  if hx <> 0 then
  begin
    postmessage(Hx, wm_keydown, VK_CONTROL, 0);       //Send Ctrl down
          postmessage(Hx, wm_keydown, VkKeyScan('s'), 0);   //Send 's' down
          postmessage(Hx, wm_keyup, VkKeyScan('s'), 0);     //Send 's' up
          postmessage(Hx, wm_keyup, VK_CONTROL, 0);         ////Send Ctrl up
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Screencast - Getting to Know the Pipeline
Suggested Courses

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question