Reputation: 151264
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
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
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.
Upvotes: 1
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
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
Reputation: 54625
I guess 2 things:
Upvotes: 1