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_LBUTTONDOWN
and
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