Simulate Mouse Click in GM 1.4

The goal here might sound pretty straightforward. Unfortunately, GM 1.4 does not provide anything directly out of the box that simulates a mouse click for that covers all implementations. It’s important to understand that in GM there are (almost always) multiple ways to achieve the exact same result. In the case of “Mouse Click” you can (1) use the explicit Event (Mouse Left Pressed/Released, etc) or (2) add a if mouse_check_button_pressed(mb_left) into the Step Event. A true mouse click simulation must ensure that the code we expect to invoke will be called when the function runs. For easy verification I created a button object that will show_message("Worked!") when it’s been clicked. I also defined another object with the same logic moved into the Mouse Left Pressed event so we ensure any method we come up will work in both scenarios. Assuming our function signature is simulate_left_click(x,y) we need to do 2 things; move the mouse to the coordinates and input a left mouse click at the current location. Luckily for us GML does provide the function window_mouse_set(x,y) which allows us to set the mouse location relative to the running game window. It works like a charm but we still need to figure out how to properly simulate a click. Intuition lead me to try event_perform but that will only handle 1 of the cases we are trying to solve for. If the mouse click logic is inside the Step Event it will never be triggered, so the solution won’t work for us. After some googling around it became clear that GML didn’t have anything in the language to do what we wanted. Since I am programming on Windows 10 I figured it would be worth exploring if we could do anything fancy in a dll to simulate a click that way (think game hacking / botting tricks). Fortunately we’ve been writing stupid hacks for old games lately and our Win32/DirectX research is going to come in handy! I won’t go into details about how to implement a dll for GM as there’s already plenty of information on the nets about that. First thing I tried was Win32’s SendInput as described here is alright for applications that aren’t running with DirectX.. For more information on why DirectX input vs Win32 see this SO post about simulating a mouse click in Warcraft3. The big idea is that since GM games are run with DirectX we must send DirectX input messages with SendMessage in order for anything to happen. We can actually checkout what messages are being send to the window while its being interacted with normally (image of messages seen by Spy++) From that we can see that we need to send WM_LBUTTONDOWNand WM_LBUTTONUP and everything should magically work.
extern "C" __declspec (dllexport) double __cdecl simulate_click() { 
HWND hWnd = GetForegroundWindow();
SendMessage(hWnd, WM_LBUTTONDOWN, 0, NULL);
SendMessage(hWnd, WM_LBUTTONUP, 0, NULL);
return 0;
And it does! We now import the dll and add the function call to our script and we have a true mouse simulation! For this being used in the wild see my Hobo Test Framework project
This entry was posted in GameMaker, testing. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *