1

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.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Hammadzafar
  • 480
  • 1
  • 7
  • 21
  • possible duplicate of [How can a program control another program?](http://stackoverflow.com/questions/1032489/how-can-a-program-control-another-program) – rufanov Oct 22 '14 at 07:15
  • P/Invoke [SendInput function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310%28v=vs.85%29.aspx) – Sriram Sakthivel Oct 22 '14 at 07:17
  • actually no. i dont need to create a bot. I am trying to create a sort of driver for another Software. But i can not work with only Keystrokes, i need to initiate moust events as well. I am trying to do it in C# and no other language... – Hammadzafar Oct 22 '14 at 07:18
  • @SriramSakthivel Sir, I know that a win32 api can be used to move the mouse but that does not hold, because if the user switches focus from the application, the mouse event will probably hit some other application. `SendKeys.SendWait()` sends the keys , i need something similar for mouse. – Hammadzafar Oct 22 '14 at 07:22
  • If you know the window handle, then use `PostMessage`. You can get an [idea here](http://www.dreamincode.net/forums/topic/200043-simulate-mouse-click-to-non-foreground-window-using-sendmessage/) – Sriram Sakthivel Oct 22 '14 at 07:25
  • thanks @SriramSakthivel. I know the window handle, and i was able to send the keystrokes in foreground, i needed to do the same even if the app is in background. Thanks. The link you provided is in **C++**, Can you kindly let me know if you know the similar **library** or **api** in **C#** – Hammadzafar Oct 22 '14 at 07:34

1 Answers1

3

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
Yogibear
  • 153
  • 12