nonopolarity
nonopolarity

Reputation: 151264

How can I accurately program an automated "click" on Windows?

I wrote a program to click on an application automatically at scheduled time using Win32, using MOUSE_DOWN and MOUSE_UP. It usually works well, except I found that I need to put in a

sleep 0.1

between the MOUSE_DOWN and MOUSE_UP. (using Ruby, which allows sleeping a fraction of a second).

Without the sleep, sometimes the click doesn't go through. But I noticed that sometimes, the click is "too long". The click is actually on a Flash app's Right Arrow. This right arrow will go to the next item on a list. So if you MOUSE_DOWN for a little longer, it actually will shift 2 or 3 items instead of just 1 item.

So I wonder, is there a way to accurately simulate 1 click in this case. Probably there is no MOUSE_CLICK event? It has to be simulated using MOUSE_DOWN and MOUSE_UP?

(it is actually called MOUSEEVENTF_LEFTDOWN and MOUSEEVENTF_LEFTUP on Win32, just for simplicity it is stated as MOUSE_DOWN instead.)

Upvotes: 0

Views: 1197

Answers (6)

Kevin Montrose
Kevin Montrose

Reputation: 22611

What function(s) are you using to accomplish this?

I'd expect SendInput with a chain of 2 passed in MOUSEINPUT structures (one button down, the other button up) would pull this off for you. You can even play games with the timestamps on the faked events to more deterministic behavior than you'll get with sleep().

There's no CLICK to send, as its the responsibility of an application to collapse low level events (mouse move, button down, button up, key down, key up, etc.) into "user level" events.


Some code, to clarify. This is straight-up untested/compiled C (read: the bad kind of C), but I hope it illustrates my point.

LPINPUT events = (LPINPUT)malloc(sizeof(INPUT) * 2);

events[0].type = INPUT_MOUSE;
events[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
events[0].mi.time = 0; //Here, you can play with timestamps (milliseconds)
events[1].type = INPUT_MOUSE;
events[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
events[1].mi.time = 0; //Likewise

//Push both events into the event queue
SendInput(2, events, sizeof(INPUT));

I have zero Ruby experience, so I don't know how you'd interop this for your case.

Upvotes: 1

Julian H
Julian H

Reputation: 1859

I'd use AutoHotKey. It's open source and free, been around a long time and actively maintained, to the point that others have built an IDE for it. I use it for generating unique random test data for form testing but it does mouse stuff too.

http://www.autohotkey.com/

Upvotes: 1

Sinan Ünür
Sinan Ünür

Reputation: 118166

You do not decide what delay setting between mouse down and mouse up results in a valid single click, the operating system does.

No sleep function can guarantee the timing between the mouse down and mouse up events you want. Perl's Win32::GuiTest module allows you to send an actual click event rather than messing with the timing of down and up events. Later: Looking at the source code, Win32::GuiTest seems to just fire mouse down and up events without any delay between them see GuiTest.pm:

elsif ( $item =~ /leftclick/i ) {
    SendLButtonDown ();
    SendLButtonUp ();
}

In addition, http://msdn.microsoft.com/en-us/library/ms646260(VS.85).aspx states that mouse_event has been superseded by SendInput http://msdn.microsoft.com/en-us/library/ms646310(VS.85).aspx which allows you to send a MOUSEINPUT event with timestamps etc.

Upvotes: 3

Jon Grant
Jon Grant

Reputation: 11520

Since the Windows API supports sleeping down to 1 millisecond, why not just sleep a shorter time? 0.01 seconds should be enough?

Upvotes: 1

jitter
jitter

Reputation: 54625

I guess 2 things:

  1. I bet ruby doesn't and can't guarantee that sleep 0.1 really sleeps only 0.1 seconds. As this is probably out of rubys control and OS controlled
  2. The call to the Win32 API via Win32 itself may take an arbitrary time and cause the delay

Upvotes: 1

scable
scable

Reputation: 4084

If you're not bound to a specific language you could have a look at AutoIt which is made especially for things like this. I had good experiences with it for automating things like mouseclicks or keystrokes.

Upvotes: 3

Related Questions