How to automate mouse actions - c++

I need to automate some mouse actions.
I need to do
mousemove1, lbuttondown1, wait1, mousemove1, lbuttonup1, wait1,
mousemove2, lbuttondown2, wait2, mousemove2, lbuttonup2, wait2,
...
The actions have to work regarding screen coordinates. The window which have to accept an event is the top window at this point.
There is a file with data.
For example
500 450 1000 500 300 2000
600 450 1000 600 300 5000
What did I try to do
#include <fstream>
#include <vector>
#include <windows.h>
struct A
{
POINT point1;
unsigned sleep1;
POINT point2;
unsigned sleep2;
A() { point1.x = point1.y = sleep1 = point2.x = point2.y = sleep2 = 0; }
};
void f(const A &a)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, a.point1.x, a.point1.y, 0, 0);
mouse_event(MOUSEEVENTF_MOVE, a.point1.x, a.point1.y, 0, 0);
Sleep(a.sleep1);
mouse_event(MOUSEEVENTF_LEFTUP, a.point2.x, a.point2.y, 0, 0);
mouse_event(MOUSEEVENTF_MOVE, a.point2.x, a.point2.y, 0, 0);
Sleep(a.sleep2);
}
int main()
{
std::vector<A> as;
std::ifstream fin("params.txt");
if (fin) {
A a;
while (fin.good()) {
fin >> a.point1.x;
fin >> a.point1.y;
fin >> a.sleep1;
fin >> a.point2.x;
fin >> a.point2.y;
fin >> a.sleep2;
if (fin.eof()) {
break;
}
as.push_back(a);
}
}
for (;;) {
for (const A &a : as) {
f(a);
}
}
}
Something is happening but I can not understand what is and where is a mistake.

A problem with your code is that you are using mouse_event with screen coordinates rather than normalized absolute coordinates. Normalized absolute coordinates always range between (0,0) in the top-left corner to (65535,65535) in the bottom-right corner, no matter what the desktop size happens to be.
The MouseTo function in the example below accepts screen coordinates as inputs, then uses the dekstop window's size to convert to normalized absolute coordinates. This example uses SendInput, which supersedes mouse_event, but they both use the same coordinates. I'm not sure if mouse_event can take the MOUSEEVENTF_VIRTUALDESK flag, but this is for supporting multi-monitor desktops.
If you wish build this example, start with a new Win32 Console application.
#include <Windows.h>
#include <cmath>
void MouseTo(int x, int y) {
RECT desktop_rect;
GetClientRect(GetDesktopWindow(), &desktop_rect);
INPUT input = {0};
input.type = INPUT_MOUSE;
input.mi.dwFlags =
MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
input.mi.dx = x * 65536 / desktop_rect.right;
input.mi.dy = y * 65536 / desktop_rect.bottom;
SendInput(1, &input, sizeof(input));
}
void MouseLButton(bool tf_down_up) {
INPUT input = {0};
input.type = INPUT_MOUSE;
input.mi.dwFlags = tf_down_up ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(input));
}
void MouseLButtonDown() { MouseLButton(true); }
void MouseLButtonUp() { MouseLButton(false); }
void AnimatedDrag(const POINT& from, const POINT& to) {
static const double iteration_dist = 20;
static const DWORD iteration_delay_ms = 1;
const double dx = to.x - from.x;
const double dy = to.y - from.y;
const double dist = sqrt(dx*dx + dy*dy);
const int count = static_cast<int>(dist / iteration_dist);
MouseTo(from.x, from.y);
MouseLButtonDown();
for(int i=1; i<count; ++i) {
const int x = from.x + static_cast<int>(dx * i / count);
const int y = from.y + static_cast<int>(dy * i / count);
MouseTo(x, y);
Sleep(iteration_delay_ms);
}
MouseTo(to.x, to.y);
MouseLButtonUp();
}
int main() {
// minimize console window
ShowWindow(GetConsoleWindow(), SW_SHOWMINNOACTIVE);
Sleep(500);
// Drag whatever is at the window coordinates in "from" to "to"
const POINT from = {300, 100};
const POINT to = {900, 600};
AnimatedDrag(from, to);
}

Christopher's answer should suffice, but might be a little intimidating to anyone not well-versed with C++, and just trying to hack together a click-utility. This should be easy enough to hack away at for most newbies.
Pardon the use of macros; I'm using them to make the intent of the code a little more English-friendly.
It should right-click on your primary display (unless you changed the X coordinate line as-commented) then shift a few pixels over and left-click to close the Right-click menu prompt, if one was created. You can see what else is available on MSDN for your own custom requirements.
I kept click / unclick / move as seperate actions, so things like drag & drop should be fairly intuitive to perform when starting with all the right ingredients.
#include <Windows.h>
// Uses absolute coords where the primary display starts at 0,0
// That works well with enumerated monitors structures and their reported coords.
#define QUEUE_MV_MOUSE ip.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
#define QUEUE_RC_START_MOUSE ip.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
#define QUEUE_RC_END_MOUSE ip.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
#define QUEUE_LC_START_MOUSE ip.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
#define QUEUE_LC_END_MOUSE ip.mi.dwFlags = MOUSEEVENTF_LEFTUP;
#define SEND_IT SendInput(1, &ip, sizeof(ip));
#define VIRTUAL_X_MODIFIER (65536 / GetSystemMetrics(SM_CXSCREEN));
#define VIRTUAL_Y_MODIFIER (65536 / GetSystemMetrics(SM_CYSCREEN));
int main()
{
INPUT ip;
ip.type = INPUT_MOUSE;
ip.mi.mouseData = 0;
// Change 500 to -500 for a left-hand extended display.
ip.mi.dx = 500 * VIRTUAL_X_MODIFIER;
ip.mi.dy = 1000 * VIRTUAL_Y_MODIFIER;
// Un-comment this Sleep timer if you're debugging in an IDE and need a quick pause.
// Sleep(500);
QUEUE_MV_MOUSE;
SEND_IT;
// Various users advise brief Sleep pauses between queued mouse and keyboard events.
// 500 milliseconds is probably overkill for your automation requirements.
Sleep(500);
QUEUE_RC_START_MOUSE;
SEND_IT;
Sleep(500);
QUEUE_RC_END_MOUSE;
SEND_IT;
Sleep(500);
ip.mi.dx -= 10 * VIRTUAL_X_MODIFIER;
ip.mi.dx -= 10 * VIRTUAL_Y_MODIFIER;
QUEUE_MV_MOUSE;
SEND_IT;
Sleep(500);
QUEUE_LC_START_MOUSE;
SEND_IT;
Sleep(500);
QUEUE_LC_END_MOUSE;
SEND_IT;
return 0;
}

Related

SendInput() causes infinite loop when used with GetAsyncKeyState() (WinAPI)

So I want to make when you hold down your left click, the mouse starts to click at regular intervals.
In theory all should work right, but in practice, not so well.
Anyways here is the code I am using for the detection and clicking of the mouse:
while (1)
{
if (GetAsyncKeyState(VK_LBUTTON) && GetAsyncKeyState(VK_RBUTTON))
{
if (weapon_selector == nullptr) continue;
if (weapon_selector->isSemiAutomatic)
{
for (Vector2I x : weapon_selector->recoilTable)
{
// Detect for hardware click instead
if (!(GetAsyncKeyState(VK_LBUTTON) & 0x8000) || !GetAsyncKeyState(VK_RBUTTON)) // This right here should detect if you are not holding either of the left or right mouse buttons, and thus abort the movement/clicks of the mouse
{
Utilities::SleepThread(200);
break;
}
Mouse::Click(); // Look in the code below how this is defined
Mouse::MoveRelative_Lerp(x.x, x.y, (int)weapon_selector->repeatDelay); // This is essentially doing this_thread::sleep_for() for around 150 ms every time after the click has happened, which would give plenty of time for the GetAsyncKeyState() function to "update" or whatever if it needed it. This function only moves the mouse, it does not click anywhere!
}
Utilities::SleepThread(200);
}
else
{
...
}
}
Utilities::SleepThread(1);
}
Here is my implementation for the Mouse::Click() function:
void Mouse::Click()
{
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = NULL;
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input.mi.time = 0;
input.mi.dwExtraInfo = NULL;
SendInput(1, &input, sizeof(input));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(input));
}
I tried pretty much everything I could think of to fix this with no success, like Mouse low level hook, also checking the injected flag in low level mouse hook, Detecting hardware mouse clicking with RegisterRawInputDevices() (with no success either), setting virtualClick variables and all kinds of different checks, no luck.. im tired trying to do this for the past 2 days
I would appreciate it a lot if someone has dealt with this before and can help me.
Minimal reproducible example:
main.cpp
#include <Windows.h>
#include <hidusage.h>
#include <iostream>
#include <cmath>
#include <string>
#include <thread>
#include <atomic>
#include <vector>
#include <fstream>
#include "Mouse.hpp"
#include "Utils.hpp"
#include "Vector2_int.hpp"
struct WeaponData
{
const char* szName;
std::vector<Vector2I> recoilTable;
int repeatDelay;
int magCapacity;
bool isSemiAutomatic;
};
#pragma region Recoil Tables
WeaponData RecoilTables[] = {
{"Revolver", {}, 175, 8, true},
{"SAR", {}, 175, 16, true},
{"SAP (P2000)", {}, 150, 10, true},
{"Python", {}, 150, 6, true},
{"Thompson", {}, 130, 20, false},
{"Custom SMG", {}, 100, 24, false},
{"AK", {}, 133, 30, false},
{"MP5", {}, 100, 30, false},
{"LR300", {}, 120, 30, false},
{"M92", {}, 150, 15, true},
{"M249", {}, 120, 100, false},
{"M39", {}, 200, 20, true},
};
#pragma endregion
void populate_recoil_table(WeaponData* data)
{
if (data->recoilTable.size() > 0) return;
for (int i = 0; i < data->magCapacity; i++)
{
data->recoilTable.push_back({0, 0});
}
}
int main()
{
WeaponData* weapon_selector = &RecoilTables[0];
populate_recoil_table(weapon_selector);
// just to see the movement of the mouse
weapon_selector->recoilTable.at(0).x = 20;
weapon_selector->recoilTable.at(0).y = 20;
while (1)
{
if (GetAsyncKeyState(VK_LBUTTON) && GetAsyncKeyState(VK_RBUTTON))
{
if (weapon_selector == nullptr) continue;
if (weapon_selector->isSemiAutomatic)
{
for (Vector2I x : weapon_selector->recoilTable)
{
if (!(GetAsyncKeyState(VK_LBUTTON) & 0x8000) || !(GetAsyncKeyState(VK_RBUTTON) & 0x8000))
{
puts("stopped bcs no buttons hold");
Utilities::SleepThread(200);
break;
}
puts("clicking");
Mouse::Click();
Utilities::SleepThread(weapon_selector->repeatDelay);
}
Utilities::SleepThread(200);
}
else
{
for (Vector2I x : weapon_selector->recoilTable)
{
if (!GetAsyncKeyState(VK_LBUTTON) || !GetAsyncKeyState(VK_RBUTTON)) { Utilities::SleepThread(200); break; }
Mouse::MoveRelative_Lerp(x.x, x.y, (int)weapon_selector->repeatDelay);
}
Utilities::SleepThread(200);
}
}
Utilities::SleepThread(1);
}
}
Mouse::Click() function
void Mouse::Click()
{
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = NULL;
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
input.mi.dx = 0;
input.mi.dy = 0;
input.mi.time = 0;
input.mi.dwExtraInfo = NULL;
SendInput(1, &input, sizeof(input)); // First send UP event to "unclick" our mouse button
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; // Then send DOWN event to click and hold the button
SendInput(1, &input, sizeof(input));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP; // Then send UP again to release it to simulate a click
SendInput(1, &input, sizeof(input));
}
Utilities::SleepThread() function
void SleepThread(uint32_t milliseconds)
{
std::chrono::high_resolution_clock::time_point target = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(milliseconds);
while (std::chrono::high_resolution_clock::now() < target)
{
std::this_thread::yield();
}
}
Things to note for the example:
Vector2I is essentially struct with 2 ints: x and y, with some function to add,subtract,etc..
weapon_selector->recoilTable is initialized, its not emtpy! Look at populate_recoil_table() function
The code is compiled with C++17 (MSVC compiler/Visual Studio 2019)
EDIT: I fixed my issue
I had to first "unpress" my button then send DOWN message again, idk why i didnt think of it earlier, the only downside is that the last message before the function ends is DOWN, so the mouse is "stuck" for a little bit (cannot be noticed) but it updates straight away if your physical button is not pressed.
Fixed click function:
void Mouse::Click()
{
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = NULL;
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
input.mi.dx = 0;
input.mi.dy = 0;
input.mi.time = 0;
input.mi.dwExtraInfo = NULL;
SendInput(1, &input, sizeof(input));
Utilities::SleepThread(10); // The application im targeting doesnt get the update if its instant mouse press, thus waiting a little
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(input));
}

How to automate Drag&Drop using SendInput

I want to test a flash application running on browser. I need to drag pieces around in the application. I want to do this by simulating mouse movements using windows api.
Here is my navie solution to simulate a mouse drag:
void MoveMouse(LPINPUT input, int x, int y) {
input->type = INPUT_MOUSE;
input->mi.dx = x*(65536/GetSystemMetrics(SM_CXSCREEN));
input->mi.dy = y*(65536/GetSystemMetrics(SM_CYSCREEN));
input->mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
}
void LeftDownMouse(LPINPUT input, int x, int y) {
input->type = INPUT_MOUSE;
input->mi.dx = x*(65536/GetSystemMetrics(SM_CXSCREEN));
input->mi.dy = y*(65536/GetSystemMetrics(SM_CYSCREEN));
input->mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
}
void LeftUpMouse(LPINPUT input, int x, int y) {
input->type = INPUT_MOUSE;
input->mi.dx = x*(65536/GetSystemMetrics(SM_CXSCREEN));
input->mi.dy = y*(65536/GetSystemMetrics(SM_CYSCREEN));
input->mi.dwFlags = MOUSEEVENTF_LEFTUP;
}
void DragMouse(LPINPUT inputs, int startX, int startY, int dropX, int dropY) {
MoveMouse(&inputs[0], startX, startY);
LeftDownMouse(&inputs[1], startX, startY);
LeftUpMouse(&inputs[2], startX, startY);
LeftDownMouse(&inputs[3], startX, startY);
MoveMouse(&inputs[4], dropX, dropY);
LeftUpMouse(&inputs[5], dropX, dropY);
}
int _tmain(int argc, _TCHAR* argv[])
{
INPUT inputs [6] = {};
// Assume there is a maximized window, mouse drags the window from 40, 10 to 100,100 coordinates.
DragMouse(inputs, 40, 10, 100, 100);
SendInput(6, inputs, sizeof(INPUT));
Sleep(1000);
return 0;
}
This code mostly doesn't work, sometimes works, it has undefined behaviour. What could be the problem? How can i solve this?
I had a similar problem with drag and drop, although my results were consistent in that the mouse was moving but not the item being dragged.
Your MoveMouse function is missing the MOUSEEVENTF_LEFTDOWN flag. Try input->mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN;
Without the flag setting you are just asking the mouse to move without the left mouse button being down.
Edit
I just checked my implementation and I don't set coordinates when pressing or releasing the mouse buttons. Only when moving.
As for variance in results, you may stop these by zeroing out the INPUT before setting fields.

How to create a full screen window on the current monitor with GLFW

Creating a window with GLFW3 is done using glfwCreateWindow:
GLFWwindow* glfwCreateWindow ( int width,
int height,
const char *title,
GLFWmonitor *monitor,
GLFWwindow *share
)
If the monitor parameter is not NULL, the window is created in full screen mode on the given monitor. One can receive the primary monitor by calling glfwGetPrimaryMonitor, or chose one of the results of glfwGetMonitors. But how can I create a full screen window on the current monitor, i.e. the monitor the window is currently running in windowed mode? There seems to be no way to receive the currently used monitor. There is glfwGetWindowMonitor, but it only returns the monitor in full screen mode, NULL in windowed mode.
You can find the current monitor with glfwGetWindowPos/glfwGetWindowSize.
This function returns the monitor that contains the greater window area.
static int mini(int x, int y)
{
return x < y ? x : y;
}
static int maxi(int x, int y)
{
return x > y ? x : y;
}
GLFWmonitor* get_current_monitor(GLFWwindow *window)
{
int nmonitors, i;
int wx, wy, ww, wh;
int mx, my, mw, mh;
int overlap, bestoverlap;
GLFWmonitor *bestmonitor;
GLFWmonitor **monitors;
const GLFWvidmode *mode;
bestoverlap = 0;
bestmonitor = NULL;
glfwGetWindowPos(window, &wx, &wy);
glfwGetWindowSize(window, &ww, &wh);
monitors = glfwGetMonitors(&nmonitors);
for (i = 0; i < nmonitors; i++) {
mode = glfwGetVideoMode(monitors[i]);
glfwGetMonitorPos(monitors[i], &mx, &my);
mw = mode->width;
mh = mode->height;
overlap =
maxi(0, mini(wx + ww, mx + mw) - maxi(wx, mx)) *
maxi(0, mini(wy + wh, my + mh) - maxi(wy, my));
if (bestoverlap < overlap) {
bestoverlap = overlap;
bestmonitor = monitors[i];
}
}
return bestmonitor;
}
After discussion on IRC it seems that it is not possible to retrieve the currently active monitor (as in the monitor the window is currently drawn on) with GLFW. Therefore it is not possible to create a full screen window on the current monitor.
EDIT: Even though there is no GLFW functionality to directly achieve this, the answer of Shmo provides an elegant solution.
Here is Shmo's answer, ported over to LWJGL:
/** Determines the current monitor that the specified window is being displayed on.
* If the monitor could not be determined, the primary monitor will be returned.
*
* #param window The window to query
* #return The current monitor on which the window is being displayed, or the primary monitor if one could not be determined
* #author Shmo<br>
* Ported to LWJGL by Brian_Entei */
#NativeType("GLFWmonitor *")
public static final long glfwGetCurrentMonitor(long window) {
int[] wx = {0}, wy = {0}, ww = {0}, wh = {0};
int[] mx = {0}, my = {0}, mw = {0}, mh = {0};
int overlap, bestoverlap;
long bestmonitor;
PointerBuffer monitors;
GLFWVidMode mode;
bestoverlap = 0;
bestmonitor = glfwGetPrimaryMonitor();// (You could set this back to NULL, but I'd rather be guaranteed to get a valid monitor);
glfwGetWindowPos(window, wx, wy);
glfwGetWindowSize(window, ww, wh);
monitors = glfwGetMonitors();
while(monitors.hasRemaining()) {
long monitor = monitors.get();
mode = glfwGetVideoMode(monitor);
glfwGetMonitorPos(monitor, mx, my);
mw[0] = mode.width();
mh[0] = mode.height();
overlap =
Math.max(0, Math.min(wx[0] + ww[0], mx[0] + mw[0]) - Math.max(wx[0], mx[0])) *
Math.max(0, Math.min(wy[0] + wh[0], my[0] + mh[0]) - Math.max(wy[0], my[0]));
if (bestoverlap < overlap) {
bestoverlap = overlap;
bestmonitor = monitor;
}
}
return bestmonitor;
}

How to move mouse with c++

I want to move the mouse cursor with a c++ script. I am using Visual C++ 2010 Express in a Windows 7 inside Parallels and I created a console application.
I know SetCursorPos method but it is just not working (it does nothing).
I managed to simulate clicks with SendInput but it does not actually move the mouse.
This is my code:
#include <Windows.h>
#include <Tlhelp32.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
void mouseLeftClick(const int x, const int y);
// window
HWND hWindow;
int main()
{
// find window
hWindow = FindWindow(NULL, "Calculadora");
if (NULL == hWindow) {
OutputDebugStringA("Couldn't find application.");
}else{
if (!SetForegroundWindow(hWindow)) {
OutputDebugStringA("Couldn't set application to foreground.");
}else{
// click on 1
mouseLeftClick(20 265));
Sleep(500);
// click on 2
mouseLeftClick(60, 265);
Sleep(500);
}
}
return 0;
}
void mouseLeftClick(const int x, const int y)
{
// get the window position
RECT rect;
GetWindowRect(hWindow, &rect);
// calculate scale factor
const double XSCALEFACTOR = 65535 / (GetSystemMetrics(SM_CXSCREEN) - 1);
const double YSCALEFACTOR = 65535 / (GetSystemMetrics(SM_CYSCREEN) - 1);
// get current position
POINT cursorPos;
GetCursorPos(&cursorPos);
double cx = cursorPos.x * XSCALEFACTOR;
double cy = cursorPos.y * YSCALEFACTOR;
// calculate target position relative to application
double nx = (x + rect.left) * XSCALEFACTOR;
double ny = (y + rect.top) * YSCALEFACTOR;
INPUT Input={0};
Input.type = INPUT_MOUSE;
Input.mi.dx = (LONG)nx;
Input.mi.dy = (LONG)ny;
// set move cursor directly and left click
Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;
SendInput(1,&Input,sizeof(INPUT));
}
This happens in Parallels because of SmartMouse is On or on Auto.
In order for a program in Parallels VM to control the mouse with SetCursorPos you need to hide cursor first. You can do that with ShowCursor(0); before you do any mouse movement e.g. SetCursorPos.
Now you will be able to control the mouse while SmartMouse is set to Auto or Off.
I found the problem. It turns out Parallels has a feature called Smart Mouse that allows you move freely between OSX and Windows. Once I deactivated it, mouse moved as expected.

How to simulate a mouse movement

How can I simulate a mouse event causing the pointer to move 500 pixels to the left, then click using C++. How would I do something like this?
Here's some modified Win32 code I had lying around:
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
#define X 123
#define Y 123
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 800
void MouseSetup(INPUT *buffer)
{
buffer->type = INPUT_MOUSE;
buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.mouseData = 0;
buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
buffer->mi.time = 0;
buffer->mi.dwExtraInfo = 0;
}
void MouseMoveAbsolute(INPUT *buffer, int x, int y)
{
buffer->mi.dx = (x * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (y * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);
SendInput(1, buffer, sizeof(INPUT));
}
void MouseClick(INPUT *buffer)
{
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN);
SendInput(1, buffer, sizeof(INPUT));
Sleep(10);
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP);
SendInput(1, buffer, sizeof(INPUT));
}
int main(int argc, char *argv[])
{
INPUT buffer[1];
MouseSetup(&buffer);
MouseMoveAbsolute(&buffer, X, Y);
MouseClick(&buffer);
return 0;
}
You'll need to call MouseSetup() to each INPUT buffer before you use it.
Resources
MSDN - SendInput()
MSDN - INPUT
MSDN - MOUSEINPUT
Here is a solution using Xlib for those who use Linux :
#include <X11/Xlib.h>
#include<stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void mouseClick(int button)
{
Display *display = XOpenDisplay(NULL);
XEvent event;
if(display == NULL)
{
fprintf(stderr, "Errore nell'apertura del Display !!!\n");
exit(EXIT_FAILURE);
}
memset(&event, 0x00, sizeof(event));
event.type = ButtonPress;
event.xbutton.button = button;
event.xbutton.same_screen = True;
XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
event.xbutton.subwindow = event.xbutton.window;
while(event.xbutton.subwindow)
{
event.xbutton.window = event.xbutton.subwindow;
XQueryPointer(display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
}
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");
XFlush(display);
usleep(100000);
event.type = ButtonRelease;
event.xbutton.state = 0x100;
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");
XFlush(display);
XCloseDisplay(display);
}
int main(int argc, char * argv[]) {
int x , y;
x = atoi(argv[1]);
y = atoi(argv[2]);
Display *display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
mouseClick(Button1);
XFlush(display);
XCloseDisplay(display);
return 0;
}
Just Build it and then to simulate a click at x ,y do:
$ ./a.out x y
i.e.
$g++ -lX11 sgmousesim2.cpp
$./a.out 123 13
Use SendInput to generate the input you want to simulate. From MSDN documentation:
Synthesizes keystrokes, mouse motions, and button clicks.
I have never did this using C++. Nevertheless, there is a Java class called Robot which is able to produce mouse events. I used this back on Java version 1.4 but it does still work. I tried the example from this Simulate a physical mouse move in Mac OS X. It runs smoothly with Oracle Java 1.6.0_26 on MacOSX Lion. The good about Java is that it is platform independent.
import java.awt.AWTException;
import java.awt.Robot;
public final class MovingMouseDemo
{
public static void main(String[] args) throws AWTException
{
Robot robot = new Robot();
robot.setAutoDelay(5);
robot.setAutoWaitForIdle(true);
//put mouse in the top left of the screen
robot.mouseMove(0, 0);
//wait so that you can see the result
robot.delay(1000);
//put the mouse 200 pixels away from the top
//10 pixels away from the left
robot.mouseMove(200, 10);
robot.delay(1000);
robot.mouseMove(40, 130);
}
}
You can still use JNI to bind it with C++.
I hope it helps
C++ alone can't do this. It has no concept of a "mouse", let alone a "click".
You need some sort of library which talks to your windowing system. For example, QT. Then it's a matter of searching through the API and making the right C++ calls.
Use the mouse_event function.