自动化测试和做外挂的原理很相似,都是模拟用户的鼠标和键盘操作,给自己的程序写自动化就是做测试,给别人的程序写自动化就是外挂了。
本文使用的技术也同样适用制作“对对碰”,"找茬"之类游戏的外挂。
阅读目录
QQ连连看外挂实现原理
GUI自动化测试的原理
什么是句柄
P/Invoke机制
获取游戏窗体的句柄
分析游戏窗口
对游戏窗口进行截图
根据游戏规则来写算法
模拟鼠标点击
源代码下载
QQ连连看外挂实现原理1.先调用Win32API获取"连连看"游戏窗口的句柄,
2.根据游戏窗口的句柄,然后获取游戏方块中的像素。
3.用一个二维数组来保存每个方块的像素
GUI自动化测试的原理什么是句柄所有的Windows控件本质上都是一个窗体(Window).每个控件/窗体都有一个与之关联的句柄(handle),可以通过这个句柄来访问,操纵和检测这个控件/窗体
窗体句柄是由系统产生的一个值,你可以把它想象成与窗体关联的一个ID,通过这个ID可以访问相应的窗体。
在.NET中,句柄的类型是,有点类似Int型。
P/Invoke机制P/invoke机制叫做"平台调用"机制,因为Win32API函数是Windows操作系统的一部分,所以它是用传统的C++程序写的,而不是用C中可以调用Win32API函数.
具体的解决方案是:先为想要使用的Win32函数创建一个C中,给这个Win32函数创建别名函数
需要先引用命名空间:;
[DllImport("",EntryPoint="FindWindow",CharSet=)]publicstaticexternIntPtrFindWindow(stringlpClassName,stringlpWindowName);DllImport:指定要使用的函数所在的DLL文件。
EntryPoint:Win32API函数的名称.
:让.NET框架来决定如何进行字符类型转换
当为一个Win32函数编写相应的C中的别名函数FindWindow(),就相当于调用了Win32API的FindWindow()函数
FindWindow函数接收2个参数,className或者WindowName然后返回句柄.
Spy++是.NET中自带工具,我们可以使用它来获取窗体的名字。
如下图。可以得到游戏窗体的名字叫"QQ游戏-连连看角色版"

这样我们就能轻松获取游戏窗体的句柄
IntPtrwndPane=(null,"QQ游戏-连连看角色版");分析游戏窗口
通过屏幕标尺工具,我们去测量游戏窗口。(这个比较繁琐,需要你多次去测量,多次调整后才能得到准确的数据).
可以发现"游戏区域"距离游戏窗口水平方向:15像素,垂直方向:182像素
游戏中垂直方向有11个方块,水平方向有19个方块
每个方块长:31像素,宽:35像素如下图

一个方块有31*35=1085个像素,事实上我们不需要获取方块中所有的像素点。为了节省性能,我只需要获取一个方块中的几个像素就可以了。
我们需要用到2个函数来实现获取方块的像素。
[DllImport("")]publicstaticexternIntPtrGetDC(IntPtrhwnd);[DllImport("")]publicstaticexternuintGetPixel(IntPtrhdc,intnXPos,intnYPos);GetDC函数的作用是指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,它的输入参数是窗口的句柄,(上节中我们介绍过可以使用FindWindow函数来获取窗口的句柄).返回的是DC句柄。(注意这两个句柄是不同的)
GetPixel根据GetDC获取的DC句柄和X坐标,Y坐标来获取像素点。
实例:我们获取游戏中"第三排第四列"的方块的像素,代码如下:

IntPtrwndPane=(null,"QQ游戏-连连看角色版");IntPtrhdc=(wndPane);//X轴方向的像素要这么算15+31*3//因为游戏区域距离游戏窗口左边15像素,每个方块宽31像素,//Y轴方向的像素要这么算182+35*4//因为游戏区域距离游戏窗口上方182,每个方块高35像素uintcolor=(hdc,15+31*3+offX,182+35*4+offY);

我们用一个二维数组来保存游戏中的所有方块
privateBlock[,]blocks=newBlock[11,19];
Block对象代表一个方块,如果方块为空,那么Block包含的是背景色。如果有方块,那么Block对象中保存该方块的9个像素点。
详细请参考代码中的Block对象。
然后分析游戏规则来写算法来遍历二维数组。
垂直方向,如果两个一样的方块,处于同样的Y轴上,中间没有任何方块可以消,如图

水平方向,如果两个一样的方块,处于同样的X轴上,中间没有任何方块,可以消,如图

拐1个弯,如果两个一样的方块,其中一个的X轴和另一个Y成90度,并且中间没有任何方块,可以消,如图

拐2个弯,如图
根据上面这些游戏规则,来设计算法,具体算法请参考源代码
模拟鼠标点击其中的一个win32API方法为
[DllImport("")]publicstaticexternintmouse_event(intdwFlags,intdx,intdy,intcButtons,intdwExtraInfo);constintMOUSEEVENTF_MOVE=0x0001;//移动鼠标publicconstintMOUSEEVENTF_LEFTDOWN=0x0002;//模拟鼠标左键按下publicconstintMOUSEEVENTF_LEFTUP=0x0004;//模拟鼠标左键抬起constintMOUSEEVENTF_RIGHTDOWN=0x0008;//模拟鼠标右键按下constintMOUSEEVENTF_RIGHTUP=0x0010;//模拟鼠标右键抬起constintMOUSEEVENTF_MIDDLEDOWN=0x0020;//模拟鼠标中键按下constintMOUSEEVENTF_MIDDLEUP=0x0040;//模拟鼠标中键抬起constintMOUSEEVENTF_ABSOLUTE=0x8000;//标示是否采用绝对坐标源代码下载留言昂