Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate mouse clicks and keypresses in F#

I'm doing a program that's supposed to move the mouse around and press automatically at places where I specify in the code. Right now i've managed to move the cursor by using this line: Cursor.Position <- System.Drawing.Point(x,y)

What I haven't found out yet is how to simulate mouseclicks or keypresses. The only thing I found about this is the SendKeys Class from MSDN (http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx). I tried to simulate a keypress with this class, but I get a run-time error message.

The line I use is: SendKeys.Send("{ENTER}")

The error message I get: "SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method."

So I replaced it with the SendWait method, but it still doesn't seem to send the keypress. How do I do this? What I really want the finished program to be able to do, is sending keys and mouse clicks to another program that is already open in the background. For example, painting an image in Paint automatically.

like image 644
Alex Avatar asked Nov 14 '10 14:11

Alex


2 Answers

If you want to avoid Win32 native interop, Windows Input Simulator is a promising looking managed wrapper around SendInput. But the latest release doesn't support mouse simulation. However, the active trunk has a patch for supporting mouse simulation (see this discussion). The project is using VS2010 C#, and you can export and build yourself from the subversion repository here.

If you are interested in Win32 native interop, I put together a demonstration of how to use the SendInput API with F#. This application simulates a right click.

open System
open System.Runtime.InteropServices

type MOUSEINPUT = struct
    val dx:int
    val dy:int
    val mouseData:int
    val dwFlags:int
    val time:int
    val dwExtraInfo:int
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

type INPUT = struct
    //need to escape traditional INPUT identifier here since "type" is a reserved word
    //though could use any other identifier name if so desired
    val ``type``:int //0 is mouse
    val mi:MOUSEINPUT
    new(_type, _mi) = {``type``=_type; mi=_mi}
end

let MOUSEEVENTF_RIGHTDOWN = 0x0008
let MOUSEEVENTF_RIGHTUP = 0x0010

[<DllImport("user32.dll", SetLastError=true)>]
extern uint32 SendInput(uint32 nInputs, INPUT* pInputs, int cbSize)

let mutable inputRightDown = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTDOWN, 0, 0))
let mutable inputRightUp = INPUT(0, MOUSEINPUT(0, 0, 0, MOUSEEVENTF_RIGHTUP, 0, 0))

SendInput(uint32 1, &&inputRightDown, Marshal.SizeOf(inputRightDown))
SendInput(uint32 1, &&inputRightUp, Marshal.SizeOf(inputRightUp))

On second reading of your question, I see that ultimately you want to send simulated mouse and keyboard events to an application running in the background, in which case SendMessage / PostMessage may be more appropriate APIs. This will still require native interop, and hopefully my example using SendInput will help. Here is a related question.

like image 115
Stephen Swensen Avatar answered Oct 25 '22 11:10

Stephen Swensen


You're looking for the SendInput Win32 API call.

like image 2
SLaks Avatar answered Oct 25 '22 10:10

SLaks