Kilo King
Kilo King

Reputation: 199

PostMessage not clicking buttons

I've played with PostMessage just clicking different tabs which seemed to work. But I'm trying to automate some button clicks and when running this function it highlights the button as if I was hovering over it but doesn't click. I thought somehow the button changing of colour made the boolean false so I added the exception of the buttons colour whilst it's hovered. Made no difference, and I do not wish to use SetCursorPos & simulate a mouseclick using SendInput. I wish to understand the problem/issue I'm having as to why it's not clicking.

void click(const std::vector<uint_16>& x, const uint_16& y)
{
    for(uint_8 i = 0; i < 5; i++)
    {
        if(content::MyClass().firstMatch(GetPixel(hdc, x[i], y)))
        {
            PostMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(x[i], y));
            return;
        }
    }
    if(content::MyClass().secondMatch(GetPixel(hdc, x[4], y)))
    {
        PostMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(x[4], y));
    }
}

Upvotes: 0

Views: 3298

Answers (1)

Serdalis
Serdalis

Reputation: 10489

The solution you are using is unreliable because you are short-circuiting the input system on the window and not specifically targeting which button you are trying to press.

As for the reason your code is not currently working, you only send a WM_LBUTTONDOWN message to the window. Since most buttons work off a combination of WM_LBUTTONDOWN and WM_LBUTTONUP your program isn't causing the buttons click method to activate.

Adding PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(x[i], y)); after the mouse down will cause the button click to register.

In future as a more reliable solution that will specifically target a button on the window and click it you may want to look at the BM_CLICK PostMessage argument. Using this instead of trying to emulate a mouse click is more correct because windows will trigger events that may otherwise be forgotten when using the mouse down and mouse up post commands.

An example:

int retVal = 0;
HANDLE hwndDialog;
HANDLE hwndButton;

/* First, see if the dialog box (titled "Inactivity Warning" ) is currently open. */
hwndDialog = FindWindow( 0, "Inactivity Warning" );
if ( hwndDialog == 0 ) return;

/* Now get a handle to the "Resume" button in the dialog. */
hwndButton = FindWindowEx( hwndDialog, 0, 0, "Resume" );

/* After making sure that the dialog box is the active window, click "Resume". */
retval = SetActiveWindow( hwndDialog );

/* converted from SendMessage. */
retval = PostMessage( hwndButton, BM_CLICK, 0, 0 ); 

Source found Here, Converted from VB by me.

For some further reading on the input system Here is a good article.
A Blog Post by Raymond Chen goes into a bit of detail about these commands and their caveats as well.

Upvotes: 4

Related Questions