游戏程序的操作不外乎两种——键盘输入控制和鼠标输入控制,几乎所有游戏中都使用鼠标来改变角色的位置和方向,本文主要是讲述如何使用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;  //StructLayoutnamespace 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按钮,其运行结果如下图所示:

可以看到当运行程序勾选"查看鼠标运行的轨迹"并点击"开始"按钮后,会通过FindWindow和FindWindowEx函数查找窗体"Form1"的"button1"按钮,并通过mouse_event移动鼠标和点击鼠标.其中函数原型为:

IntPtr FindWindowEx(IntPtr hwndParent,     // handle to parent window [父窗体句柄]IntPtr hwndChildAfter, // handle to child window [子窗体句柄]string strClass,       // class name [窗体类名]string strWindow       // window name [窗体名]
);

但是怎样找到窗体类名和按钮的类名呢?由于初学,很多窗体我都没有实现如QQ,它需要用到一个叫spy++的工具.
PS:第一次制作gif格式动态图片,参照博客 http://blog.csdn.net/tangcheng_ok/article/details/8246792

三. 使用SPY++工具获取窗体信息

如果修改代码为:

//获取任务栏句柄
IntPtr ptrTaskbar = FindWindow("Shell_TrayWnd",null);
//托盘通知句柄
IntPtr ptrStartBtn = FindWindowEx(ptrTaskbar, IntPtr.Zero, "TrayNotifyWnd", null);  

可以获取电脑底部任务栏的托盘通知句柄,其中通过Spy++工具(VS中"工具"中自带)查找如下图所示:

同样,我通过spy++工具获取txt句柄,首先打开spy++工具,同时点击"查找窗口"按钮(望远镜),再点击"查找程序工具"中按钮拖拽至要查看的窗体中,点击"确定"按钮.

这样就会显示这个txt的信息,同时可以右击"属性"显示窗体的类名、窗体题目、句柄等信息.

最后通过下面代码可以获取hello.txt的句柄:

//获取记事本句柄
IntPtr ptrTaskbar = FindWindow("Notepad", null);
IntPtr ptrStartBtn = FindWindowEx(ptrTaskbar, IntPtr.Zero, "Edit", null);

再通过mouse_event操作鼠标,同时可以通过SendMessage将指定的消息发送到一个或多个窗口,PostMessage将一个消息寄送到一个线程的消息队列后就立即返回.实现消息传递等功能,学习ing~

四. 总结

该篇文章主要讲述C#如何操作鼠标的事件,在制作游戏外挂或自动运行程序时非常实用,但遗憾的是在上面通过窗体名称"Form1"获取窗体时总是失败,需要通过spy++获取它的类名来实现.Why?同时如果想学习键盘模拟技术的可以研究SetWindowsHookEx(安装钩子)、CallNextHookEx(下一个钩子)、UnhookWindowsHookEx(卸载钩子)和鼠标Hook实现很多技术.
希望文章对大家有所帮助,如果有错误或不足之处,请见谅~
(By:Eastmount 2014年10月13日 晚上8点
http://blog.csdn.net/eastmount/)
参考资料-在线笔记:
本文主要参考书籍《C#网络变成高级篇之网页游戏辅助程序设计》张慧斌 王小峰著
1.C#获取QQ聊天输入框中内容
http://www.csharpwin.com/csharpspace/9133r5654.shtml
2.C#查找窗口,FindWindow用法(By-LYBwwp)http://blog.csdn.net/lybwwp/article/details/8168553
3.FindWindowEx用法(By-coolszy) http://blog.csdn.net/coolszy/article/details/5523784
4.C# 隐藏任务栏开始按钮关闭shell(By-sshhbb)http://blog.csdn.net/sshhbb/article/details/6605976
5.任务栏句柄 http://blog.csdn.net/wangjieest/article/details/6943241
6.C#如何在外部程序的密码框内自动输入密码 http://biancheng.dnbcw.info/c/117849.html
7.C#实现对外部程序的调用操作 http://www.blue1000.com/bkhtml/c17/2012-11/70993.htm
8.百度知道 C# API函数FindWindowEx返回子窗体的值为零
9.百度知道 用C#操作API实现填写桌面窗体内的textbox并点击窗体按钮

C# 系统应用之鼠标模拟技术及自动操作鼠标相关推荐

  1. python 按键精灵 离线_python,PyAutoGUI,自动操作鼠标键盘,类似按键精灵

    三个文件需在同一个文件夹下面,文件夹的位置无要求. 1.第一个文件,trial.py,python代码调用PyAutoGUI操作鼠标键盘.可以通过修改start_time和end_time来确定程序自 ...

  2. python制作自动按键精灵_python,PyAutoGUI,自动操作鼠标键盘,类似按键精灵

    三个文件需在同一个文件夹下面,文件夹的位置无要求. 1.第一个文件,trial.py,python代码调用PyAutoGUI操作鼠标键盘.可以通过修改start_time和end_time来确定程序自 ...

  3. pywinauto 记事本操作示例 移动鼠标 使用键盘 自动操作软件

    文章目录 打开程序 查看窗口 找到控件位置 查看标识符 选择菜单 点击按钮 写入内容 鼠标移动 操作键盘 from pywinauto.application import Application # ...

  4. pyautogui 的用法 python自动操作鼠标、键盘

    文章目录 安装依赖库 获取鼠标位置 鼠标绝对移动和相对移动 鼠标绝对拖动和相对拖动 鼠标点击 按下.抬起鼠标 键盘写入内容 键盘按压.释放 安装依赖库 pip install --upgrade pi ...

  5. Control Study - 键盘模拟鼠标(实现用键盘操作鼠标光标)(示例代码下载)

    (一).功能 实现用键盘模拟鼠标移动的功能,在游戏设计中常用到 *操作说明:  当运行程序后,放开鼠标,按键盘上的光标键移动,可以代替鼠标. (二).代码   1  using  System;    ...

  6. 软件功能以图找图自动点击鼠标 发现一款非常好用的以图视图自动操作软件AI万控系统和大家分享一下全名叫“AI人工智能万控系统”

    软件功能以图找图自动点击鼠标 发现一款非常好用的以图视图自动操作软件AI万控系统和大家分享一下软件功能-识图点击,自动找图点击,找图点击,找图点击软件,以图识图自动点击操作,以图识图点击操作,以图找图 ...

  7. 小学计算机课程介绍鼠标,小学信息技术《认识鼠标》

    小学信息技术<认识鼠标> 2018-11-27 <认识鼠标> ──鼠标的单击.双击和拖动 山东济宁市永丰街中心小学 翟海峰 [适用版本]小学信息技术(泰山版)教材教学案例 [适 ...

  8. 如何取消掉计算机更新图标,XP系统如何关闭右下角中的自动更新图标?

    相信大家在使用XP系统中,都有遇到过电脑右下角总是弹跳出"您的计算机可能存在风险"这是怎么回事呢?其实这是因为是系统关闭了系统自动更新,那么遇到这种问题该怎么解决呢?其实我们只要把 ...

  9. WPF窗口长时间无人操作鼠标自动隐藏

    原文:WPF窗口长时间无人操作鼠标自动隐藏 在软件开发中有时会有等待一段时间无人操作后隐藏鼠标,可能原因大致如下: 1.为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作 ...

最新文章

  1. IOS问题汇总:2012-12-18 UIAlertView+UIActionSheet
  2. 策略路由实验,指定出口
  3. Scala伴生类与伴生对象:apply方法/伴生对象可以访问伴生类的私有属性
  4. Scala函数作为函数的返回值
  5. 外部工具连接SaaS模式云数据仓库MaxCompute实战:商业BI分析工具篇
  6. Cell Phone Network
  7. Http基本身份验证在Spring Security中如何工作?
  8. ubuntu安装python下载包_Ubuntu安装Python的包管理工具Pip
  9. Android 系统性能优化(47)---Traceview
  10. 3V升压5V芯片,3V升压5V的电路图
  11. 移动机器人运动控制算法入门
  12. Game.Physics.Engine.Development(游戏物理引擎开发)
  13. 浅析VO、DTO、DO、PO的概念、区别和用处
  14. Macbook air 键盘失灵的解决方案
  15. 【实战毕业论文排版】图片添加题注实现自动编号
  16. php对接微博热搜,基于PHP爬虫的微博热搜实时监控平台
  17. Vulnhub-Pwned
  18. 用计算机教学体育,体育教学中计算机的应用
  19. 学英语《每日一歌》之because of you
  20. 单片机教学打铃控制器C语言

热门文章

  1. expdp impdp中 exclude/include 的使用
  2. mysql 5.6 安装教程
  3. LOJ P10149 凸多边形的划分 题解
  4. django 登陆增加除了用户名之外的手机和邮箱登陆
  5. Python笔记——Django路由系统
  6. linux 开机自动启动服务
  7. 有一次去校内的某个礼堂看电影,在门口有个长得很斯文的陌生人一脸神秘地跟我说:师弟,能不能进去之后,把电影票从厕所的气窗扔出来给我……...
  8. html模块化标签,jq load()方法实现html 模块化。
  9. android studio table居中代码_CSS 之 居中
  10. 实验7.2 二维数组 7-8 螺旋方阵