Search code examples
c#mouseeventsimulation

Perform a mouse Click event on another Application using C#


what i need to do is that I need to control another application installed on the same machine using my custom application. For example if i needed to use the standard windows calculator I would simply send the input events to the calculator. I have used some code snippets to make this possible and I have now triggered both mouse and keyboard events. but the problem is that i can be sure that the keyboard event will hit the target application because it has the process handle. but i cannot be sure about the mouse. and also if the target application goes into background, i cannot initiate mouse clicks on it. I need help to find a way to make sure that the mouse click is done on the application only.

I need to send mouse co-ordinates and click as well. for example "sendMouseClick("Notepad", 100, 400); which will send a click to Notepad, even though it stays minimized.

IMPORTANT NOTE

A similar question is answered previously but that is in reference to first finding the state of the other application and then sending the inputs either keyboard or mouse, what i need to do is to send an application a set of instructions that must work whether the application is in foreground or not. For "The other Guys":: if you dont want to help or cant help, thats okay but please do know that i havent stolen the question or anything. I simply want to achieve this task in C#.

The code I have to simulate keyboard key Press is:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace SimulateKeyPress
{
    partial class Form1 : Form
{
    private Button button1 = new Button();
    private Button button2 = new Button();
    private Button button3 = new Button();

    [STAThread]
    public static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }

    public Form1()
    {
        button1.Location = new Point(10, 10);
        button1.TabIndex = 1;
        button1.Text = "Click to automate Calculator";
        button1.AutoSize = true;
        button1.Click += new EventHandler(button1_Click);

        button2.Location = new Point(150, 140);
        button2.TabIndex = 0;
        button2.Text = "Click to Exit Calculator";
        button2.AutoSize = true;

        button2.Location = new Point(80, 80);
        button2.TabIndex = 2;
        button2.Text = "Click to Run Calculator";
        button2.AutoSize = true;

        button2.Click += new EventHandler(button2_Click);
        this.DoubleClick += new EventHandler(Form1_DoubleClick);

        this.Controls.Add(button1);
        this.Controls.Add(button2);
       // this.Controls.Add(button3);
    }

    // Get a handle to an application window.
    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpClassName,
        string lpWindowName);

    // Activate an application window.
    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    // Send a series of key presses to the Calculator application. 
    private void button1_Click(object sender, EventArgs e)
    {
        // Get a handle to the Calculator application. The window class 
        // and window name were obtained using the Spy++ tool.
        IntPtr calculatorHandle = FindWindow("CalcFrame", "Calculator");
        
        
        //Process firstProc = new Process();
        //firstProc.StartInfo.FileName = "calc.exe";
        //firstProc.EnableRaisingEvents = true;

        //firstProc.Start();
        
        // Verify that Calculator is a running process. 
        if (calculatorHandle == IntPtr.Zero)
        {
            MessageBox.Show("Calculator is not running.");   
            return;
        }

        // Make Calculator the foreground application and send it  
        // a set of calculations.
        SetForegroundWindow(calculatorHandle);
        SendKeys.SendWait("1024");
        SendKeys.SendWait("*");
        SendKeys.SendWait("32");
        SendKeys.SendWait("=");
    }
    private void button2_Click(object sender, EventArgs e)
    {
        System.Diagnostics.Process.Start("calc.exe");
        
    }
    private void button3_Click(object sender,EventArgs e) 
    {
        Process [] proc =Process.GetProcessesByName("Calculator");
        proc[0].Kill();
    }
    // Send a key to the button when the user double-clicks anywhere  
    // on the form. 
    private void Form1_DoubleClick(object sender, EventArgs e)
    {
        // Send the enter key to the button, which raises the click  
        // event for the button. This works because the tab stop of  
        // the button is 0.
        SendKeys.Send("{ENTER}");
    }
}
}

the previous help on stack overflow, msdn and other sites provides the code to simulate a mouse click in the same application. But i need to send mouse hits to another application.


Solution

  • Maybe this could help you

    Code

    The task

    • Getting the mouse's current position
    • Sending the mouse event

    Windows forms

    ...
    using System.Runtime.InteropServices;
    
    namespace yournamespace
    {
    
     public partial class yourclassname
     {
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
    
        private const int MOUSEEVENTF_LEFTDOWN = 0x02;
        private const int MOUSEEVENTF_LEFTUP = 0x04;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
        private const int MOUSEEVENTF_RIGHTUP = 0x10;
    
        int X = Cursor.Position.X;
        int Y = Cursor.Position.Y;
        mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
      }
    }   
    

    WPF

    Things are a bit harder in WPF

    double mousePointX;
    double mousePointY;
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetCursorPos(out POINT lpPoint);
    
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
      public int X;
      public int Y;
    
      public POINT(int x, int y)
      {
          this.X = x;
          this.Y = y;
      }
    }
    
    private void WritePoint(object sender, RoutedEventArgs e)
    {
        POINT p;
        if (GetCursorPos(out p))
        {
            System.Console.WriteLine(Convert.ToString(p.X) + ";" + Convert.ToString(p.Y));
        }
    }
    [DllImport("User32.dll")]
    static extern IntPtr GetDC(IntPtr hwnd);
    
    [DllImport("gdi32.dll")]
    static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
    
    [DllImport("user32.dll")]
    static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
    
    private Point ConvertPixelsToUnits(int x, int y)
    {
        // get the system DPI
        IntPtr dDC = GetDC(IntPtr.Zero); // Get desktop DC
        int dpi = GetDeviceCaps(dDC, 88);
        bool rv = ReleaseDC(IntPtr.Zero, dDC);
    
        // WPF's physical unit size is calculated by taking the 
        // "Device-Independant Unit Size" (always 1/96)
        // and scaling it by the system DPI
        double physicalUnitSize = (1d / 96d) * (double)dpi;
        Point wpfUnits = new Point(physicalUnitSize * (double)x,
        physicalUnitSize * (double)y);
    
        return wpfUnits;          
    }
    private void WriteMouseCoordinatesInWPFUnits()
    {
        POINT p;
        if (GetCursorPos(out p))
        {
        Point wpfPoint = ConvertPixelsToUnits(p.X, p.Y);
        System.Console.WriteLine(Convert.ToString(wpfPoint.X) + ";" +   Convert.ToString(wpfPoint.Y));
    
        mousePointY = wpfPoint.Y;
        mousePointX = wpfPoint.X
        }
    }
    

    Now the most important part of the code

     [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
    
        private const int MOUSEEVENTF_LEFTDOWN = 0x02;
        private const int MOUSEEVENTF_LEFTUP = 0x04;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
        private const int MOUSEEVENTF_RIGHTUP = 0x10;
    
        ...    
            mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP,   Convert.ToUInt32(mousePointX), Convert.ToUInt32(mousePointY), 0, 0); 
        ...
    

    Warning

    • The code is tested
    • The code is not a "copy & paste code