游戏程序的操作不外乎两种——键盘输入操控和鼠标输入操控,简直一切游戏中都运用鼠标来改动人物的方位和方向,本文首要是叙述怎么运用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按钮,其运转成果如下图所示:
能够看到当运转程序勾选“检查鼠标运转的轨道”并点击“开端”按钮后,会经过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并点击窗体按钮