• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 7253
  • Last Modified:

Clicking a button in another application

Good day all :)

I am trying to simulate a button click on another application form, I have figured it out except for one small snag.

As the second application is mine and I have the source for it, the attached code works. However when I send "ControlCaption" as an empty string, it doesn't work - I understand why but not how to get around it. I would prefer not to make unnecessary modifications to the second application.

My question: How do I simulate a button click to a TSpeedButton which a) has no handle and b) has no caption/text only an image?

Kind Regards
Procedure ClickButton(WindowName, WindowCaption,
  ControlName, ControlCaption: String);
Var
  hParent, hControl : HWND;
Begin
  hParent := 0;
  hControl := 0;

  hParent := FindWindow(pChar(WindowName), pChar(WindowCaption));

  Try
    BringWindowToTop(hParent);
    Application.ProcessMessages;

    hControl := FindWindowEx(hParent, 0, pChar(ControlName),
      pChar(ControlCaption));

    Try
      SendMessage(hControl, BM_CLICK, 0,0);
    Finally
      hControl := 0;
    End;
  Finally
    hParent := 0;
  End;
End;

// WindowName: The name of the form (eg: TForm1)
// WindowCaption: The caption of the form (eg: Form1)
// ControlName: The name of the control (eg: TButton)
// ControlCaption: The text/caption of the control (eg: Ok)

Procedure Button2Click(Sender: TObject);
Begin
  ClickButton('TForm1', 'Form1', 'TSpeedbutton', '');
End;

Open in new window

0
DeonM
Asked:
DeonM
  • 3
  • 2
1 Solution
 
ThievingSixCommented:
Hmm, try:
Procedure ClickButton(WindowName, WindowCaption,
  ControlName, ControlCaption: PChar);
Var
  hParent, hControl : HWND;
Begin
  hParent := 0;
  hControl := 0;

  hParent := FindWindow(WindowName, WindowCaption);

  Try
    BringWindowToTop(hParent);
    Application.ProcessMessages;

    hControl := FindWindowEx(hParent, 0, ControlName,
      ControlCaption);

    Try
      SendMessage(hControl, BM_CLICK, 0,0);
    Finally
      hControl := 0;
    End;
  Finally
    hParent := 0;
  End;
End;

// WindowName: The name of the form (eg: TForm1)
// WindowCaption: The caption of the form (eg: Form1)
// ControlName: The name of the control (eg: TButton)
// ControlCaption: The text/caption of the control (eg: Ok)

Procedure Button2Click(Sender: TObject);
Begin
  ClickButton('TForm1', 'Form1', 'TSpeedbutton', nil);
End;

Open in new window

0
 
epasquierCommented:
you cannot click on a button that has no window handle by this method.

Your only solution is to simulate a mouse click on the form, knowing the coordinate of the button

Also, I don't see the need to set your handles to 0 once used.

Procedure ClickSomewhere(WindowName, WindowCaption: PChar; X,Y:Integer);
Var
  hParent : HWND;
Begin
 hParent := FindWindow(WindowName, WindowCaption);
 if hParent<>0 Then
  Begin
   BringWindowToTop(hParent);
   Application.ProcessMessages; // not sure that is useful
   SendMessage(hParent, BM_CLICK, X,Y);
  End;
End;

Open in new window

0
 
DeonMAuthor Commented:
Hi ThievingSix,

Thanks for the reply.
Tried your solution, didn't work I'm afraid. :(

Kind Regards
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
epasquierCommented:
for this part :
> However when I send "ControlCaption" as an empty string, it doesn't work
> I understand why but not how to get around it.

you must use ControlCaption = NULL (nil) for a match to all window names
Procedure ClickButton(WindowName, WindowCaption, ControlName, ControlCaption: PChar);
Var
  hParent, hControl : HWND;
Begin
 hParent := FindWindow(WindowName, WindowCaption);
 if hParent<>0 Then 
  Begin
   BringWindowToTop(hParent);
   Application.ProcessMessages;
// little fix :
   if ControlCaption='' Then ControlCaption:=Nil;
   hControl := FindWindowEx(hParent, 0, ControlName,ControlCaption);
   if hControl<>0 Then SendMessage(hControl, BM_CLICK, 0,0);
  End;
End;

Open in new window

0
 
epasquierCommented:
oups, I didn't see that Thieving Six was pointing to this very same fix.

But you said it doesn't work ?

for SpeedButon, no, but it should work for handled buttons without knowing the name (there might be more than one...)
0
 
DeonMAuthor Commented:
Hi, Epasquier

Thank you for your reply.

While the code you suggested didn't work initially, with a little tweaking I managed to get it too work. While this isn't ideal, at least I know it will work for the time being.

Thank you!

Kind Regards.
Procedure TForm1.ClickSomewhere(WindowName, WindowCaption: PChar);
Var
  hParent           : HWND;
  Pos, oldPos       : TPoint;
  rect              : TRect;
Begin
  hParent := FindWindow(WindowName, WindowCaption);

  If hParent <> 0 Then
  Begin
    BringWindowToTop(hParent);

    GetWindowRect(hParent, rect);

    oldPos.X := Mouse.CursorPos.X;
    oldPos.Y := Mouse.CursorPos.Y;

    Pos.X := Rect.Left - 400;
    Pos.Y := Rect.Top - 158;
    Mouse.CursorPos := ClientToScreen(Pos);

    mouse_event(MOUSEEVENTF_LEFTDOWN, 0,0,0,0);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

    Mouse.CursorPos := oldPos;

  End;
End;

Open in new window

0

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now