I am developing an application using Windows Form (C#). I need to be able to press a button which starts monitoring the location of the next mouse-click inside another application. The coordinates of this click then need to be used to force a click on the same button later in the same application. For testing I am just using a calculator and pressing a key to capture X and Y and then pressing another button to press that key again but it's not working. Any help to figure out what I am doing wrong will be much appreciated.
I have used MouseKeyHook to subscribe to the mouse hook
nuget install MouseKeyHook
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool GetCursorPos(out Point lpPoint);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(System.Drawing.Point p);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
const int WM_LBUTTONDOWN = 0x0201;
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//Button click which starts the subscribe
private void btnStart_Click(object sender, EventArgs e)
{
Subscribe();
}
private IKeyboardMouseEvents m_GlobalHook;
public void Subscribe()
{
// Note: for the application hook, use the Hook.AppEvents() instead
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
}
Point p;
IntPtr hWnd;
private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
{
if (GetCursorPos(out p))
{
IntPtr mainWindow = WindowFromPoint(p);
hWnd = ChildWindowFromPointEx(mainWindow, p, 0x0000);
RECT rct = new RECT();
GetWindowRect(mainWindow, ref rct);
X = p.X - rct.Left;
Y = p.Y - rct.Top;
}
Unsubscribe();
}
public void Unsubscribe()
{
m_GlobalHook.MouseDownExt -= GlobalHookMouseDownExt;
m_GlobalHook.Dispose();
}
private void btnClick_Click(object sender, EventArgs e)
{
PostMessage(hWnd, WM_LBUTTONDOWN,X, Y);
}
}
```.
You cannot guarantee that the other application(calculator) responds to message you've posted.
In addition, the calculator is a UWP window, you will get an empty hWnd
with ChildWindowFromPointEx
. You should use SendInput
to simulate mouse input and ensure that the clicked place is not covered by other windows. Sample in C#: https://stackoverflow.com/a/54072028/10611792
Or use UI Automation.