Programmatically press a button on another application (C, Windows)

帅比萌擦擦* 提交于 2019-12-02 15:56:38
  1. Are you sure that "SaveButton" class name is valid? Do you get the button handle?
  2. Try to send messages to ButtonHandle window (directly to the button).

Update: I believe this should work,

SendMessage(ButtonHandle, BM_CLICK, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);

You have to send a button click twice. Not sure why (maybe the first click only activates the window of the button), but I'm using this code for a long time and it always worked for me.

See the following solution, also you can use

SendMessage(ButtonHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(ButtonHandle, WM_LBUTTONUP, 0, 0);

Or

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

HWND buttonHandle = 0;

BOOL CALLBACK GetButtonHandle(HWND handle, LPARAM)
{
 char label[100];
 int size = GetWindowTextA(handle,label,sizeof(label));
 if(strcmp(label,"&Save") == 0)
 {
  buttonHandle = handle;
  return false;
 }
 return true;
}
void main()
{
 HWND windowHandle = FindWindowA(NULL,"Do you want to Save?");
 if(windowHandle != 0)
 {
  BOOL ret = EnumChildWindows(windowHandle,GetButtonHandle,0);

  if(buttonHandle != 0)
  {
   LRESULT res = SendMessage(buttonHandle,BM_CLICK,0,0);
   //SendMessage(buttonHandle,WM_LBUTTONDOWN,0,0); 
   //SendMessage(buttonHandle,WM_LBUTTONUP,0,0);
  }

 }



}

Note: Getting sure from the window text,button text (check if there is space at the end of the window title)

Access Denied errors on SendMessage or PostMessage make no sense unless the process sending the message is running at a lower integrity level than the target process.

This should not be happening unless the process that owns the target window is being run "asAdministrator" or is a service. And its damn hard for services to create windows on the interactive desktop with Windows 6 and up.

You can do some reading about Integrity Levels Here if they apply even remotely to this situation. Internet Explorer is about the only other application that 'opts in' to the integrity security model by purposely lowering the integrity level of itself in order to sandbox itself more effectively.

If you can raise the window containing the button you can send raw mouse event to a position within the boundaries of button.

There are two function to simulate mouse event SendInput and mouse_event. I recommend using mouse_event function. To raise a window you can use ShowWindow. I don't know how to get the handle of a button, but if you have its hWnd its easy to find its absolute position using GetWindowRect function. Try using these, if you run into any problems I will be glad to help.

Or define a custom WM within your application window to handle save request. WM_CUSTOM or WM_USER (cant remember which) marks the start of user defined window messages.

When I have to do these kind of things I use SendKeys. It is VB-ish and C# provides a nice interface to use but for C/C++ you'll have to do it <this way>. What is nice with it is that you could write scripts and run them instead of hard coding it in your code.

Microsoft is now pushing Active Accessibility (MSAA) for UI Automation, (It has been renamed a number of times over the years) see

Sorry I don’t have any simple code to get you started. As “SendMessage()” does not seem to be working for you, I don’t know of another option apart from “UI Automation”

I am assuming you have check with Spy++ (installed with MsDev) that you message are being send to the correct button etc – and that the button is a standard windows buttons. My first instant would say use “SendMessage()" or "PostMessage()” but given the numbers of answers about “SendMessage()” and the fact it is not working for you. I expect someone is going on…

You can use sendkeys (as tr3 said) to send mouse clicks, which is different than using SendMessage. It is also less direct and more hack-ish, but is useful for automation (in VBS).

Also, just a guess but the problem could be that your message handling is broken somewhere by not calling the base class member. Example:

void CMyClass::OnMessageY(CWnd *cwnd)
{
    CBaseClass::OnMessageY(cwnd);
    //... my code
}

if you sure ButtonHandle are valid handle you can use pair WM_LBUTTONDOWN and WM_LBUTTONUP message instead of BN_CLICKED

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
    SendMessage(ButtonHandle, WM_LBUTTONDOWN, MK_LBUTTON, 0);
    SendMessage(ButtonHandle, WM_LBUTTONUP, MK_LBUTTON, 0);
}

A non-C approach: Use Java and the java.awt.Robot class to move the mouse around perform real clicks (I guess there is something in the Windows World for this, too). Problem: You have to know where your button is :D

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!