Skip to content
Jimb Esser edited this page Mar 10, 2015 · 1 revision

Automating mouse clicks (low level details)

srClickMouseNoMove() sends a mouse down and up event (WM_LBUTTONDOWN/WM_LBUTTONUP) at the specified coordinates, to the automated window, without moving the cursor. For games / programs, like ATITD, that listen to the coordinates of a mouse click (as opposed to polling the mouse position and processing a click whever the mouse last was), when only a click is required, this works ideally, because it does not completely steal control of the user's mouse while the macro is running. Additionally it works while the automated program's window is not even in focus! This also means that clicks are never accidentally sent to the wrong program. However, if a use us moving the mouse, or dragging something else, while this function is called, things won't work how either the script or the user expect (probably will release the user's click at the location of the script's click, or something like that).

However, if the program does not listen to mouse events in that particular way, or the operation involved requires dragging, then the mouse cursor actually needs to be moved to the appropriate location on screen. srClickMouse() uses a different API ("mouse_event") and simulates moving the mouse, waiting a moment, sending a mouse down, waiting a moment, sending a mouse up, and then waiting a moment before returning control to the script. The times needed here vary based on program and performance, generally needs to wait long enough for a "frame" of the program being automated to process, so this time may need to be adjusted based on system performance and framerate. For example, for ATITD I found the delays of 50,15,15 work well, and for Atom Zombie Smasher I had to use values of 50,100,50 for a script to be reliable. This method requires the window to be in focus, and if the window is not in focus might lose the click, since, for some programs, the first click just activates the window and is otherwise ignored.

In general, stick with srClickMouseNoMove, unless the program doesn't seem to respond to this at all, then use srClickMouse. There are more complicated things you can do to make clicks safer, check out safeClick() in common_click.inc in the scripts for ATITD.

Automating keyboard input (low level details)

There are two sets of keyboard input functions, one suffixed with "2". The original set use window messages send directly to the automated program. Like srClickMouseNoMove() above, this is ideal since it does not require the window to be in focus, does not interrupt the user as much, and cannot send keyboard input to the wrong program. However, not all programs respond to these events, and for those that don't, you can use the "2" varieties which instead make use of the "SendInput" API which should work in all programs.

void srKeyEvent(const char *s)

Sends a character or sequence of characters to the captured window. Example:

dofile("screen_reader_common.inc");
function doit()
  askForWindow();
  lsSleep(250); -- wait for shift release to make it to the window
  srKeyEvent('username\tpassword');
  lsSleep(250); -- wait a moment before submitting so we can see it work, that's more fun!
  srKeyEvent('\n');
end

This will send the string "username" followed by a tab (\t) and then the string "password" and then enter (\n).

void srKeyDown(int key)

srKeyDown() sends a key down message. When most keyboard keys are pressed, they trigger repeating messages. To simulate this, call srKeyDown() repeatedly with the same key. srKeyDown() will recognize multiple calls prior to the srKeyUp() call and send appropriate repeating key messages. Multiple keys may be down at once.

void srKeyUp(int key)

srKeyUp() sends a key up message, releasing a key pressed with srKeyDown(). To release all pressed keys, send the special key code -1.

Clone this wiki locally