Send "button pressed" message to UnityWndClass - c++

I have 3D game and i need to press buttons in this game from another application. Spy++ says that window of the game is UnityWndClass. When i pressing buttons in game, window recives only mouse messages like WM_SETCURSOR, WM_LBUTTONDOWN etc, but when i try to send WM_LBUTTONDOWN and WM_LBUTTONUP with coordinates of the button from another window nothing happend. Why? Any ideas how to press buttons?

WM_SETCURSOR is for changing the cursor image of your own window. WM_LBUTTONDOWN and WM_LBUTTONUP are notification messages sent after mouse click. WM_LBUTTONXXX messages are probably not handled by the main Window procedure.
To fake mouse input, you can use mouse_event or SendInput. For example, this moves cursor to x=10 / y=10 and and clicks left mouse.
int x = 10 * 65536 / GetSystemMetrics(SM_CXSCREEN);
int y = 10 * 65536 / GetSystemMetrics(SM_CYSCREEN);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Or use SendInput for multiple calls (see comments)
INPUT input[3];
for (int i = 0; i < 3; i++)
{
memset(&input[i], 0, sizeof(INPUT));
input[i].type = INPUT_MOUSE;
}
input[0].mi.dx = x;
input[0].mi.dy = y;
input[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(3, input, sizeof(INPUT));
Window should be at least visible and preferably be active. You can use SetForegroundWindow. See this example to make sure window is visible and active.
Other alternatives:
Use Spy++ to get information about the button which you want to press.
For example, if this was Windows Calculator, you can spy on calculator's buttons, it shows calculator button 2 has ID set to 0x84. You can send WM_COMMAND with WPARAM set to 0x84 to simulate button press.
HWND hwnd = FindWindow(0, L"Calculator");
if (IsWindow(hwnd))
{
//this should put "234" in to calculator's edit box
SendMessage(hwnd, WM_COMMAND, 0x84, 0);
SendMessage(hwnd, WM_COMMAND, 0x85, 0);
SendMessage(hwnd, WM_COMMAND, 0x86, 0);
}

Related

C++ (CLR) mouse click to hidden window

In a windows C++ CLR project I am trying to build a function that can send a mouse click to absolute x, y coords in a out of focus / minimized / hidden window.
The function is controlled by pressing a button on the app GUI.
Doing some research on google and on stackoverflow I put together the code below:
void click(int x, int y) {
POINT pt;
pt.x = x;
pt.y = y;
HWND hWnd = FindWindowEx(NULL, NULL, L"winWithThisClass", NULL);
if (hWnd)
{
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
Sleep(130);
SendMessage(hWnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}
}
The above code does send a click to the minimized window, but not at specified coords.
The click is sent to the minimized window at the coords of the mouse pressing button on the GUI.
So whereever the GUI is located on the desktop, when I press the button that runs the function, the click is sent to the minimized window at the GUI's button coords.
Any ideeas on how I can make this code work as intended?
Thanks

SendMessage C++ Right mouse button doesn't work left mouse button works?

I want to use SendMessage to complete part of my remote control program. Case I think it will control the computer program without make it get focus.
Here is my demo. I use windows mspaint to test it. It works when I post "Left button down", so I am sure that my HWND is right(The drawing area handle got by spy++ or some similar tools). It draws a point in my "drawing area" in mspaint.
But when I select a color and run the folling code. It doesn't work. Nothing happens in my drawing area on the same mspaint program.
Here is my code:
#include <stdio.h>
#include <Windows.h>
int main(){
HWND hwnd;
printf("Please input your handle\n");
scanf("%d", &hwnd);
int x = 100, y = 100;
//int right = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y)); //It works
int wrong = SendMessageA(hwnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(x, y)); //It doesn't work
printf("%d", wrong);
printf("%d", GetLastError());
return 0;
}
I am confused because the two lines are so similar. Is there any bugs in mspaint?
I am confused because the two lines are so similar. Is there any bugs
in mspaint?
These two code lines can be executed successfully and they do send WM_LBUTTONDOWN and WM_RBUTTONDOWN messages to the target window. I can confirm this via target a own created window application and monitor mouse message in it. So maybe the difference depends on how does the mspaint application handle left and right mouse button click.
The following code works for me for both left and right mouse buttons. You can have a try.
int x = 100, y = 100;
// Left mouse button click
int lResult = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
Sleep(500);
lResult = SendMessageA(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
x += 10;
// Right mouse button click
int rResult = SendMessageA(hwnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(x, y));
Sleep(500);
rResult = SendMessageA(hwnd, WM_RBUTTONUP, MK_RBUTTON, MAKELPARAM(x, y));
printf("Done.");
The test result of above code:
Note: As other communities already pointed out, using SendInput instead of SendMessage to Synthesizes keystrokes, mouse motions, and button clicks.

Why PostMessage with WM_LBUTTONDBLCLK does not work?

I run this code:
LPPOINT pp = new POINT;
GetCursorPos(pp);
while(1){
PostMessage(GetDesktopWindow(), WM_LBUTTONDBLCLK, 0, MAKELPARAM(pp->x, pp->y));
Sleep(1000);
}
It does not click on the point indicated by the cursor, but opens and closes the Start menu
.Please tell me what's wrong
Sending WM_LBUTTONDBLCLK to an arbitrary window handle or to the desktop will not simulate a mouse click.
You can use SendInput, however, which can simulate a mouse click given screen coordinates (not a window handle, or window or client coordinates). This code will simulate a left-button click at the current cursor position:
INPUT in[2]; // 0 = left dn, 1 = left up
ZeroMemory(in, sizeof(INPUT) * 2);
in[0].type = INPUT_MOUSE;
in[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
in[1].type = INPUT_MOUSE;
in[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(2, in, sizeof(INPUT));
Note that you can also use mouse_event, but SendInput is preferred according to the official documentation on MSDN.

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));
}
}
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.

C++ simulate left mouse click on minimized program

I have been searching for a bit about this particular problem I am having, I want to be able to simulate a left mouse click on a program that I am currently attached to.
Right now, I create a thread that checks a database for certain values, and when those values come back (the ones I am looking for), I want to be able to then send a left mouse click in any x,y coord of the program (while minimized).
How can this be done for Windows 7? Thanks!
EDIT: Here is how I am calling the thread ...
HWND child = GetActiveWindow();
if ( child == NULL )
MessageBox(0,"Couldn't get the child hwnd!","",0);
DWORD ID;
HANDLE thread_check_game = CreateThread ( NULL , 0 , (LPTHREAD_START_ROUTINE) game_check_thread , (LPVOID)child, 0 , &ID ); CloseHandle ( game_check_thread );
and then ...
DWORD WINAPI game_check_thread(LPVOID lpParam) {
HWND Window;
Window = (HWND)lpParam;
// ... some other code ...
// ...
WORD mouseX = 398;
WORD mouseY = 398;
SendMessage(Window,WM_LBUTTONDOWN,MK_LBUTTON,MAKELPARAM(mouseX,mouseY));
SendMessage(Window, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(mouseX, mouseY));
Write("Sent Left Click\n");
ExitThread(0);
return 0;
}
If you want to fire a mouse event in your application, use the SendMessage function, and your message will appear in the window with handle hWnd's message pump.
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(mousePosX, mousePosY));
You may need to notify for WM_LBUTTONUP, depending on the way you application handles it's mouse events.