以编程方式在另一个窗口中单击鼠标
本文关键字:单击 鼠标 窗口 另一个 编程 方式 | 更新日期: 2023-09-27 18:32:32
在不将鼠标移动到另一个位置的情况下以编程方式单击另一个窗口中的某个位置,即使窗口不在顶部?我想向另一个窗口发送一种消息,以模拟鼠标单击某个位置。
我试图用PostMessage来完成这个:
PostMessage(WindowHandle, 0x201, IntPtr.Zero, CreateLParam(300,300));
PostMessage(WindowHandle, 0x202, IntPtr.Zero, CreateLParam(300,300));
我以这种方式创建了 CreateLParam 函数:
private static IntPtr CreateLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
问题是窗户被锁定在他的位置上。我认为我的应用程序单击了 (1,1) 坐标。有些人可以帮助我解决这个问题吗?
编辑:这是帖子消息:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr WindowHandle, int Msg, IntPtr wParam, IntPtr lParam);
0x201和0x202分别是WM_LBUTTONDOWN和WM_LBUTTONUP。
你不能通过发送消息来做到这一点,而是使用SendInput Windows API。
调用方法ClickOnPoint,这是表单点击事件的示例,所以this.handle
是表单句柄,请注意,这些是窗口女巫手柄上的客户端坐标,您可以轻松更改此坐标并发送屏幕坐标,在这种情况下,您不需要下面的句柄或ClientToScreen调用。
ClickOnPoint(this.Handle, new Point(375, 340));
更新:现在使用SendInput,tnx Tom。
顺便说一句。我只使用了此示例所需的声明,对于更多内容,有一个不错的库:Windows 输入模拟器(C# 发送输入包装器 - 模拟键盘和鼠标)
public class ClickOnPointTool
{
[DllImport("user32.dll")]
static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
#pragma warning disable 649
internal struct INPUT
{
public UInt32 Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
[StructLayout(LayoutKind.Explicit)]
internal struct MOUSEKEYBDHARDWAREINPUT
{
[FieldOffset(0)]
public MOUSEINPUT Mouse;
}
internal struct MOUSEINPUT
{
public Int32 X;
public Int32 Y;
public UInt32 MouseData;
public UInt32 Flags;
public UInt32 Time;
public IntPtr ExtraInfo;
}
#pragma warning restore 649
public static void ClickOnPoint(IntPtr wndHandle , Point clientPoint)
{
var oldPos = Cursor.Position;
/// get screen coordinates
ClientToScreen(wndHandle, ref clientPoint);
/// set cursor on coords, and press mouse
Cursor.Position = new Point(clientPoint.X, clientPoint.Y);
var inputMouseDown = new INPUT();
inputMouseDown.Type = 0; /// input type mouse
inputMouseDown.Data.Mouse.Flags = 0x0002; /// left button down
var inputMouseUp = new INPUT();
inputMouseUp.Type = 0; /// input type mouse
inputMouseUp.Data.Mouse.Flags = 0x0004; /// left button up
var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
/// return mouse
Cursor.Position = oldPos;
}
}
我过去发现了一种向Windows Media Player发送消息的方法所以我用它来模拟我想要的应用程序中的点击!
使用此类(下面的代码)查找窗口并发送所需的消息!
using System;
using System.Runtime.InteropServices;
namespace Mouse_Click_Simulator
{
/// <summary>
/// Summary description for Win32.
/// </summary>
public class Win32
{
// The WM_COMMAND message is sent when the user selects a command item from
// a menu, when a control sends a notification message to its parent window,
// or when an accelerator keystroke is translated.
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_COMMAND = 0x111;
public const int WM_LBUTTONDOWN = 0x201;
public const int WM_LBUTTONUP = 0x202;
public const int WM_LBUTTONDBLCLK = 0x203;
public const int WM_RBUTTONDOWN = 0x204;
public const int WM_RBUTTONUP = 0x205;
public const int WM_RBUTTONDBLCLK = 0x206;
// The FindWindow function retrieves a handle to the top-level window whose
// class name and window name match the specified strings.
// This function does not search child windows.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindow(string strClassName, string strWindowName);
// The FindWindowEx function retrieves a handle to a window whose class name
// and window name match the specified strings.
// The function searches child windows, beginning with the one following the
// specified child window.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindowEx(
int hwndParent,
int hwndChildAfter,
string strClassName,
string strWindowName);
// The SendMessage function sends the specified message to a window or windows.
// It calls the window procedure for the specified window and does not return
// until the window procedure has processed the message.
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
[MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
int lParam); // second message parameter
}
}
例如:
Win32.SendMessage(iHandle, Win32.WM_LBUTTONDOWN, 0x00000001, 0x1E5025B);
这是我创建的应用程序源代码,用于在特定时间间隔内自动单击"BlueStacks"应用程序!
对于FindWindow
,wParam
,lParam
等,你可以随时问我怎么做!这并不难:) ;)希望它有帮助!:)
我无法添加注释:D
为我工作:
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd,
int Msg,
int wParam,
IntPtr lParam);
并像这样在 lParam 中组合坐标:
private static IntPtr CreateLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
并使用:
Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONDOWN, 0x00000001, CreateLParam(150,150));
Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONUP, 0x00000000, CreateLParam(150, 150));
0x00040156 - 窗口句柄。
我正在寻找使用间谍++的窗口手柄每次都是新的,所以最好使用FindWindow。
附言
应用程序窗口的屏幕截图,即使窗口不在顶部
https://stackoverflow.com/a/911225/12928587
我使用这个解决方案。 工作得很好。