views:

464

answers:

6

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.)

+3  A: 

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.

daddz
+1  A: 

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.

Kevin Montrose
I am using mouse_event = user32 'mouse_event' , ['L' , 'L' , 'L' , 'L' , 'L' ], 'V' and then mouse_event.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 to send the event... how do I play with the timestamps instead of using sleep?
動靜能量
Added some code to illustrate how I'd try to do this in C. Its completely untested, but hopefully helps.
Kevin Montrose
+1  A: 

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
jitter
+1  A: 

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

Jon Grant
i think i have seen cases where 0.01 may not register as a click... but i can try more
動靜能量
+3  A: 

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.

Sinan Ünür
is it true that the Flash app can still take that click to be longer than usual and shift 2 items?
動靜能量
+1  A: 

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/

Julian