5

is it possible to simulate Click on a process without actually clicking on it?

e.g. I wanna Click on a running Calculator with mouse stand still. is this possible?

MBZ
  • 26,084
  • 47
  • 114
  • 191
  • what language are you looking to do this in? you tagged winapi and C, C++, or C# are all valid candidates. also, what are you looking to click on? a button? a specific coordinate? – rrhartjr Jul 27 '12 at 14:19
  • doesn't matter. any of them is OK :) but I prefer C#, C++ and Python. – MBZ Jul 27 '12 at 14:20
  • @MBZ Well, better check here then: http://stackoverflow.com/questions/2416748/how-to-simulate-mouse-click-in-c – Snow Blind Jul 27 '12 at 14:46
  • 4
    Use the automation interfaces. That's what they're for. – Raymond Chen Jul 27 '12 at 17:11

1 Answers1

9

If you are just trying to click a button within a fairly typical labels, fields, and buttons application, you can use a little bit of P/Invoke to use FindWindow and SendMessage to the control.

If you are not already familiar with Spy++, now is the time to start!

It is packaged with Visual Studio 2012 RC in: C:\Program Files\Microsoft Visual Studio 11.0\Common7\Tools. It should be similarly found for other versions.

Try this as Console C# application:

class Program
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

    private const uint BM_CLICK = 0x00F5;

    static void Main(string[] args)
    {
        // Get the handle of the window
        var windowHandle = FindWindow((string)null, "Form1");

        // Get button handle
        var buttonHandle = FindWindowEx(windowHandle, IntPtr.Zero, (string)null, "A Huge Button");

        // Send click to the button
        SendMessage(buttonHandle, BM_CLICK, 0, 0); 
    }
}

This gets the handle to the window captioned "Form1". Using that handle, it gets a handle to the Button within the Window. Then sends a message of type "BM_CLICK" with no useful params to the button control.

I used a test WinForms app as my target. A single button and some code behind to increment a counter.

A Test WinForms App

You should see the counter increment when you run the P/Invoke console application. However, you will not see the button animate.

You could also use the Spy++ Message Logger function. I recommend a filter to BM_CLICK and maybe WM_LBUTTONDOWN/WM_LBUTTONUP (what a manual click will give you).

Hope that helps!

rrhartjr
  • 2,112
  • 2
  • 15
  • 21