How to Simulate a Mouse Movement

How to simulate a mouse movement

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

How to simulate mouse cursor movement in C++

You will need to gradually progress your mouse a little bit at a time. Consider, for example the following pseudo-code function:

def moveMouse (endX, endY, stepCount, stepDelay):
GetCurrentPosTo(startX, startY);
for step = 1 to stepCount
currX = startX + (endX - startX) * step / stepCount
currY = startY + (endY - startY) * step / stepCount
SetCurrentPosFrom(currX, currY)
DelayFor(stepDelay)
endfor
enddef

This calculates the current position (within the loop) as some fraction of the journey from (startX, startY) to (endX, endY), adjusting for the number of steps you wish to take.

So using a stepCount of 100 and stepDelay of ten milliseconds, the mouse cursor would smoothly move over the period of a second.

There could be other possibilities such as moving the cursor at a specific speed rather than taking a specific time, or specifying a minimum speed and maximum time to combine both methods.

I'll leave that as an extra exercise. Suffice to say it would involve the same method of moving the cursor a little at a time rather than just setting its position to the final value immediately.

How to simulate mouse click along with mouse move using javascript

You cannot move the mousepointer with javascript, because of the security implications that it incurs.

Simulate mouse click without moving the cursor

Is there a way to simulate a mouseclick on a spot on the screen relative to the Windows location without actually moving the cursor?

To answer your specific question - NO. Mouse clicks can only be directed where the mouse cursor actually resides at the time of the click. The correct way to simulate mouse input is to use SendInput() (or mouse_event() on older systems). But those functions inject simulated events into the same input queue that the actual mouse driver posts to, so they will have a physical effect on the mouse cursor - ie move it around the screen, etc.

How do I simulate input without SendInput?

SendInput operates at the bottom level of the input stack. It is just a backdoor into the same input mechanism that the keyboard and mouse drivers use to tell the window manager that the user has generated input. The SendInput function doesn't know what will happen to the input. That is handled by much higher levels of the window manager, like the components which hit-test mouse input to see which window the message should initially be delivered to.

When something gets added to a queue, it takes time for it to come out the front of the queue

When you call Send­Input, you're putting input packets into the system hardware input queue. (Note: Not the official term. That's just what I'm calling it today.) This is the same input queue that the hardware device driver stack uses when physical devices report events.

The message goes into the hardware input queue, where the Raw Input Thread picks them up. The Raw Input Thread runs at high priority, so it's probably going to pick it up really quickly, but on a multi-core machine, your code can keep running while the second core runs the Raw Input Thread. And the Raw Input thread has some stuff it needs to do once it dequeues the event. If there are low-level input hooks, it has to call each of those hooks to see if any of them want to reject the input. (And those hooks can take who-knows-how-long to decide.) Only after all the low-level hooks sign off on the input is the Raw Input Thread allowed to modify the input state and cause Get­Async­Key­State to report that the key is down.

The only real way to do what you are asking for is to find the HWND of the UI control that is located at the desired screen coordinates. Then you can either:

  1. send WM_LBUTTONDOWN and WM_LBUTTONUP messages directly to it. Or, in the case of a standard Win32 button control, send a single BM_CLICK message instead.

  2. use the AccessibleObjectFromWindow() function of the UI Automation API to access the control's IAccessible interface, and then call its accDoDefaultAction() method, which for a button will click it.

That being said, ...

I don't have access to the buttons handle that is supposed to be clicked.

You can access anything that has an HWND. Have a look at WindowFromPoint(), for instance. You can use it to find the HWND of the button that occupies the desired screen coordinates (with caveats, of course: WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, when will it all end?).

AutoIt Automation - How To Simulate Human Like Cursor Movement

Thanks to a comment made on my question. That linked to a script. It works amazingly!

It produces nonlinear mouse movements better than I ever imagined :)

; Smoother Mouse Move
; by the DtTvB

; Ease in function
func __calci1($i, $sm)
return $i ^ $sm;
endFunc

; Ease out function
func __calci2($i, $sm)
return 1 - ((1 - $i) ^ $sm);
endFunc

; Ease in out function
func __calci($i, $sm)
if ($i < 0.5) then
return __calci1($i * 2, $sm) / 2;
else
return (__calci2(($i - 0.5) * 2, $sm) / 2) + 0.5;
endIf
endFunc

; Ease backward function
func __calof($i, $sm)
if ($i < 0.5) then
return __calci($i * 2, $sm);
else
return __calci((1 - $i) * 2, $sm);
endIf
endfunc

; MAIN FUNCTION
func mouseMove2($x2, $y2)
$x1 = mouseGetPos(0);
$y1 = mouseGetPos(1);
$xv = random(-100, 100);
$yv = random(-100, 100);
$sm = random(1.5, 2.5);
$m = random(50, 160);
for $i = 0 to $m
$ci = __calci($i / $m, $sm);
$co = __calof($i / $m, $sm);
$cx = $x1 + (($x2 - $x1) * $ci) + ($xv * $co);
$cy = $y1 + (($y2 - $y1) * $ci) + ($yv * $co);
mouseMove ($cx, $cy, 1);
next
endFunc

; Test Script
mouseMove2 (512, 386);


Related Topics



Leave a reply



Submit