当前位置:首页 > Windows程序 > 正文

[转]C# 系统应用之鼠标模拟技术及自动操作鼠标

2021-03-28 Windows程序

原文网址: C# 系统应用之鼠标模拟技术及自动操作鼠标

       游戏程序的操作不外乎两种——键盘输入控制和鼠标输入控制,几乎所有游戏中都使用鼠标来改变角色的位置和方向,本文主要是讲述如何使用C#调用Windows API函数实现鼠标模拟操作的功能.首先通过结合FindWindow和FindWindowEx寻找到窗体的按钮,在通过SetCursorPos或mouse_event函数操作鼠标,同时涉及到通过spy++工具获取窗体消息的信息.

一. Windows API函数介绍

.NET没有提供改变鼠标指针位置、模拟单机操作的函数,但是可以通过调用Windows API函数实现.

[DllImport("user32.dll")] static extern bool SetCursorPos(int X,int Y);

该函数用于设置鼠标的位置,其中X和Y是相对于屏幕左上角的绝对位置.

[DllImport("user32.dll")] static extern void mouse_event(MouseEventFlag flags,int dx,int dy,uint data,UIntPtr extraInfo);

该函数不仅可以设置鼠标指针绝对位置,而且可以以相对坐标来设置位置.

其中flags标志位集,指定点击按钮和鼠标动作的多种情况.dx指鼠标沿x轴绝对位置或上次鼠标事件位置产生以来移动的数量.dy指沿y轴的绝对位置或从上次鼠标事件以来移动的数量.data如果flags为MOUSE_WHEEL则该值指鼠标轮移动的数量(否则为0),正值向前转动.extraInfo指定与鼠标事件相关的附加32位值.

[DllImport("user32.dll")] static extern IntPtr FindWindow(string strClass, string strWindow);

该函数根据类名和窗口名来得到窗口句柄,但是这个函数不能查找子窗口,也不区分大小写.如果要从一个窗口的子窗口查找需要使用FIndWindowEX函数.

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

该函数获取一个窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配,该函数查找子窗口时从排在给定的子窗口后面的下一个子窗口开始.其中参数

hwnParent为要查找子窗口的父窗口句柄,若该值为NULL则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口.
hwndChildAfter子窗口句柄,查找从在Z序中的下一个子窗口开始,子窗口必须为hwnParent直接子窗口而非后代窗口,若hwnChildAfter为NULL,查找从父窗口的第一个子窗口开始.
strClass指向一个指定类名的空结束字符串或一个标识类名字符串的成员的指针.
strWindow指向一个指定窗口名(窗口标题)的空结束字符串.若为NULL则所有窗体全匹配.
返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄,如果函数失败,返回值为NULL.

二. 鼠标自动点击按钮和查看鼠标运行轨迹

首先创建一个C#工程,设计的窗体如下图所示,同时添加Timer时间器控件:

技术分享


然后添加的如下代码,即可实现鼠标模拟技术及自动操作鼠标:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; //引用新命名空间 using System.Runtime.InteropServices; //StructLayout namespace MouseAction { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //结构体布局 本机位置 [StructLayout(LayoutKind.Sequential)] struct NativeRECT { public int left; public int top; public int right; public int bottom; } //将枚举作为位域处理 [Flags] enum MouseEventFlag : uint //设置鼠标动作的键值 { Move = 0x0001, //发生移动 LeftDown = 0x0002, //鼠标按下左键 LeftUp = 0x0004, //鼠标松开左键 RightDown = 0x0008, //鼠标按下右键 RightUp = 0x0010, //鼠标松开右键 MiddleDown = 0x0020, //鼠标按下中键 MiddleUp = 0x0040, //鼠标松开中键 XDown = 0x0080, XUp = 0x0100, Wheel = 0x0800, //鼠标轮被移动 VirtualDesk = 0x4000, //虚拟桌面 Absolute = 0x8000 } //设置鼠标位置 [DllImport("user32.dll")] static extern bool SetCursorPos(int X, int Y); //设置鼠标按键和动作 [DllImport("user32.dll")] static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo); //UIntPtr指针多句柄类型 [DllImport("user32.dll")] static extern IntPtr FindWindow(string strClass, string strWindow); //该函数获取一个窗口句柄,该窗口雷鸣和窗口名与给定字符串匹配 hwnParent=Null从桌面窗口查找 [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string strClass, string strWindow); [DllImport("user32.dll")] static extern bool GetWindowRect(HandleRef hwnd, out NativeRECT rect); //定义变量 const int AnimationCount = 80; private Point endPosition; private int count; private void button1_Click(object sender, EventArgs e) { NativeRECT rect; //获取主窗体句柄 IntPtr ptrTaskbar = FindWindow("WindowsForms10.Window.8.app.0.2bf8098_r11_ad1", null); if (ptrTaskbar == IntPtr.Zero) { MessageBox.Show("No windows found!"); return; } //获取窗体中"button1"按钮 IntPtr ptrStartBtn = FindWindowEx(ptrTaskbar, IntPtr.Zero, null, "button1"); if (ptrStartBtn == IntPtr.Zero) { MessageBox.Show("No button found!"); return; } //获取窗体大小 GetWindowRect(new HandleRef(this, ptrStartBtn), out rect); endPosition.X = (rect.left + rect.right) / 2; endPosition.Y = (rect.top + rect.bottom) / 2; //判断点击按钮 if (checkBox1.Checked) { //选择"查看鼠标运行的轨迹" this.count = AnimationCount; movementTimer.Start(); } else { SetCursorPos(endPosition.X, endPosition.Y); mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, UIntPtr.Zero); mouse_event(MouseEventFlag.LeftUp, 0, 0, 0, UIntPtr.Zero); textBox1.Text = String.Format("{0},{1}", MousePosition.X, MousePosition.Y); } } //Tick:定时器,每当经过多少时间发生函数 private void movementTimer_Tick(object sender, EventArgs e) { int stepx = (endPosition.X - MousePosition.X) / count; int stepy = (endPosition.Y - MousePosition.Y) / count; count--; if (count == 0) { movementTimer.Stop(); mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, UIntPtr.Zero); mouse_event(MouseEventFlag.LeftUp, 0, 0, 0, UIntPtr.Zero); } textBox1.Text = String.Format("{0},{1}", MousePosition.X, MousePosition.Y); mouse_event(MouseEventFlag.Move, stepx, stepy, 0, UIntPtr.Zero); } } }

同时自定义一个对话框,增加一个button按钮,其运行结果如下图所示:

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/68782.html