recent

Please accept my apologies for the mess — the site is under construction.

previous

about / contact

the site
the webmaster

full cv (pdf)


github
form
linkedin
youtube


writing

the Lorentz boost (coming soon)







C++ | Mouse Utility | "Auto Clicker"
13:07 24-Aug-12

This relatively simple code allows the user to automate several system mouse events and read cursor location. It is designed to run in a windows environment.

The code is split into several functions so that various actions (such as left mouse click; read mouse position; etc.) may be called whenever. I have defined each function as a void function, meaning that it returns no values. While it might make more sense to define some functions as int functions (returning an integer), such as in the case of getting a method type (explained later) or returning mouse cursor position; it turns out using pointers and 'global' variables works just as well and eliminates the need to worry about values being passed around.

In the precode 'includes' section, you'll see the inclusion of a definition, among standard library loading. To be honest, I'm not entirely sure what this does, but I am fairly confident that it explains to the compiler what sort of windows.h library to load from, as far as specific functions go. But again, I am not sure. I only know that it was required for my compiler (Dev C++ 4.9.9.2) to not throw errors. Also, it so happens that 0x501 should replace 0x500 for some systems.
#define _WIN32_WINNT 0x500


#include <iostream>
#include <windows.h>
If you happen to be intimately familiar with what's going on here, I'd love to hear from you by email.


The next two functions are pretty standard. void printSpash prints the program splash screen and void getMethod allows the user to specify code functionality. Perhaps of note is the replacement of the normal cout with std::cout. This relates to the cout command (used to write text to the screen) to the std namespace. A lot fo the time, you will see a line using namespace std; at the top of the screen: this would remove the need to precede cout with std::. Read more about namespaces here.

Now onto the fun stuff. The function void getMousePosition does exactly what you would think. The windows library we're working with here allows us to find the pixel-by-pixel position of the cursor at any time. Technically, a POINT object is returned, but all that we're really interested in here is the coordinates. We can pull these from the point by specifying that we wish to read these properties from the object by typing the object's name (we defined it earlier) and adding a .x or .y to the end of it.

// make a point and read into it, then update vars via pointers
void getMousePosition (int& xPos, int& yPos)
{
     // create POINT object named "cursorPos" for "cursor position"
     POINT cursorPos;
     // call the function "GetCursorPos" and pass it the a pointer
     // to our POINT cursorPos
     GetCursorPos(&cursorPos);
     // read the x property from cursorPos and assign it to the
     // integer variable xPos (a pointer, technically)
     xPos = cursorPos.x;
     // do the same thing for the y position
     yPos = cursorPos.y;
}

If you're familiar with the basics of C++, you might find the variable declaration to be a bit peculiar in the above snippet. You see, normally when you're defining the class of variable to be input into a function, you just write int or float or char. In this case, since I'm using a void function and will not be returning any values (like the x and y position of the cursor), I need to find another way to use these data in a meaningful way. I chose pointers. Pointers are a topic for another page but essentially, I'm telling the function to create two integer-like variables xPos and yPos whose memory locations are the same as the passed variables. Another way to think of it is to say that I am passing the actual variables into the function, not just clones of their values. Anything that I do to the variable within the function happens to the variable (that I passed in) outside of the function as well. The local variable is merely a pointer to the global one.


More fun stuff. Here we trigger a mouse-click event. Other than the (potentially) unfamiliar syntax, there should be no real surprises here. We invoke the function SendInput to tell the system something has happened. You can look up the specifics of the function on MSDN for yourself, if you so choose. Basically, though, what you're doing is creating an input event and sending it to the OS. See the commented code below.

// click the mouse using "SendInput"
void mouseRightClick ()
{
     // create an INPUT object named "Input"
     INPUT Input = {0};
     
     // simulate the right mouse button being pressed
     // specify the type of input as mouse
     Input.type = INPUT_MOUSE;
     // specify the action that was performed, "right down"
     Input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
     // send the input to the system
     ::SendInput(1,&Input,sizeof(INPUT));
     
     // simulate release of the right mouse button
     // clear the the "Input" object rather than assign a more memory
     ::ZeroMemory(&Input,sizeof(INPUT));
     // specify type of input
     Input.type = INPUT_MOUSE;
     // indicate that the action "right up" was performed
     Input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
     // send the input to the system
     ::SendInput(1,&Input,sizeof(INPUT));
}

And we're done! A brief point: a mouse click event is composed of two actions, pressing the button down and releasing it. You may not have considered that before now (or you may have...). Think about the difference between clicking on an icon and dragging it. These are two totally different actions, determined by a difference in delay of the RIGHTUP event.

The whole left-click procedure is the same as the right-click, with the obvious exception of MOUSEEVENTF_RIGHTDOWN being changed to MOUSEEVENTF_LEFTDOWN.

void mouseLeftClick ()
{
     INPUT Input = {0};
     
     // left down
     Input.type = INPUT_MOUSE;
     Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
     ::SendInput(1,&Input,sizeof(INPUT));
     
     // left up
     ::ZeroMemory(&Input,sizeof(INPUT));
     Input.type = INPUT_MOUSE;
     Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
     ::SendInput(1,&Input,sizeof(INPUT));
}

And that's that.


The last cool function that we define moves the pointer. void mouseMoveTo is composed of two parts. The first finds the size of the user's screen in pixels and converts that into pointer coordinates. An annoying—but understandable—convention requires deals with screen locations in terms of absolute points; yet deals with pointer locations in terms of screen resolution. By calling the function ::GetSystemMetrics( SM_CXSCREEN ), we acquire information about the screen width. Similarly, by calling ::GetSystemMetrics( SM_CYSCREEN ) we acquire information about screen height. We then need to perform the conversion, which happens to simply be a scaling involving a factor of 65535.

The second part of the function mouseMoveTo actually does the moving of the mouse. Again, we use the ::SendInput() function; however, this time we set different values.

// finds out information about the user's current screen configuration
// then moves the cursor to the requested coordinates
void mouseMoveTo (int toX, int toY)
{
     // get system information regarding screen size / resolution
     double screenRes_width = ::GetSystemMetrics( SM_CXSCREEN )-1;
     double screenRes_height = ::GetSystemMetrics( SM_CYSCREEN )-1;
     // scale the function inputs 'toX and 'toY' appropriately by a
     // factor of 65535
     double dx = toX*(65535.0f / screenRes_width);
     double dy = toY*(65535.0f / screenRes_height);
     // we now have variables 'dx' and 'dy' with the user-desired
     // coordinates in a form that the SendInput function can understand
     
     // set up INPUT Input, assign values, and move the cursor
     INPUT Input = {0};
     // we want to be sending a MOUSE-type input
     Input.type = INPUT_MOUSE;
     // the mouse input is of the 'MOVE ABSOLUTE' variety
     Input.mi.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
     Input.mi.dx = LONG(dx);
     Input.mi.dy = LONG(dy);
     // we have given information about the magnitude of the new
     // cursor position; here we will send it
     ::SendInput(1,&Input,sizeof(INPUT));
}

Something that is rather worth noting is the fact that two different types of cursor move commands are available, and we wish to invoke a "move to absolute" behavior and accordingly do so.



And that's it!

The rest of the program should be composed of familiar—or at least identifiable—commands. I'll still outline a few of them below, though, and point out a few other specifics.

This program runs within the command-line environment, and the SetConsoleTitle() command allows you to specify what you want the name of the command prompt window to be.
SetConsoleTitle( "Auto Clicker v0.01" );
Look at the top of the window in the image below if you don't know what I'm talking about.


If you wish, you can also use labels and goto commands to structure your program. **It is generally considered bad practice to use labels and goto commands in your programs, though! If it can be done another way (and almost always: it can), it should be.** That having been said, such labels and procedural movement commands are quite easy to implement.

A label is specified by coming up with a name and following it immediately with a colon. A goto command is simply the word 'goto' followed by the label name. See the window below.
int main ()
{
     int iteration = 1;
     start:
     std::cout << "Iteration number: " << iteration << std::endl;
     goto start;
     return 0;
}

Running such a program (if it were to work) would result in a never-ending loop equivalent to the one below.
int iteration = 1;
while (true)
{
     std::cout << "Iteration number: " << iteration << std::endl;
     iteration ++;
}

Comments, questions, and suggestions welcome!

Auto Clicker program


Full colorized code here.



This website is run and maintained by George Wong. This webpage was last modified 13:07 24-Aug-12 est.
You opened this page on
www.somewhereville.com/gnw and its subsidiaries are copyright 2003-2014.