这次的教程大概是2–3篇文章,第一篇教程主要是把外挂的界面和自动开局的功能做出来,界面如下所示,大家自行用MFC创建一个这界面出来,如果搞不定,请先不要看本系列文章,先看MFC基础!

我们先把游戏置顶功能做出来,我们在资源文件选择 游戏置顶 这个控件,然后点右键–属性,在弹出来的框框中点下图的闪电处的位置

然后找到 BN_CLICKED在它后面会有个下拉框,点击下拉框的内容就行了,MFC会帮我们添加一个函数,这个函数就是点击游戏置顶会调用的函数

void CKyodaiPluginDlg::OnBnClickedCheckstick()

{

}

我们要置顶一个窗口,就要用到windowsAPI SetWindowPos

SetWindowPos函数改变一个子窗口,弹出式窗口或顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口

这个函数的第一个参数就是要置顶的窗口的句柄,第二个参数是要置顶还是不置顶,第三第四个参数表示窗口的位置,第五第六个参数表示窗口的大小,最后一个参数是表示,表示你是要改变窗口的大小还是位置还是Z秩序。

既然要窗口句柄,通过上次的学习,我们已经知道了,可以通过FindWindow获取,我们打开spy++,获取窗口的标题

由于游戏中,我们可能经常要获取窗口的句柄,所以我打算封装一个函数 用来获取窗口的句柄,这样 如果游戏更新了,窗口标题变了,也只要改一个地方就行了

HWND CKyodaiPluginDlg::GetGameHwnd()

{

return::FindWindow(NULL, L”QQ游戏 – 连连看角色版”);

}

我们接着来实现窗口置顶的响应函数

void CKyodaiPluginDlg::OnBnClickedCheckstick()

{

HWND hGame = GetGameHwnd();

if (m_checkStick.GetCheck() == BST_CHECKED)

{

//选中了,说明要置顶游戏窗口

::SetWindowPos(hGame, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

}

else

{

//取消对游戏窗口的置顶

::SetWindowPos(hGame, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

}

}

m_checkStick是窗口置顶那个空间的关联的变量

我们进函数以后有个判断,如果是选中了的话,就执行置顶。我们可以看到 if和else里面调用都是同一个函数 只是第二个参数不同,置顶是HWND_TOPMOST 取消置顶是HWND_NOTOPMOST,由于我们不改变窗口的大小和位置,所以后面4个参数传0 并且最后一个标志传SWP_NOSIZE | SWP_NOMOVE,就是告诉系统,这个窗口不变小,也不移动

我们来测试下看看 运行软件,点击游戏置顶,发现游戏窗口在上面了,点我们的软件的时候游戏还是在我们软件的上面

再取消置顶试试,我们发现,点下我们的软件,游戏窗口就在我们软件的下面了

接着,我们来完成自动开局的功能,先添加自动开局的响应函数由于跟之前窗口置顶的添加方法差不多,我就不做演示了

我们思考下,自动开局,无非就是鼠标自己过去,点下开局的按钮就行了,我们只要知道 鼠标要移动到哪里就OK了。我们打开spy++

我们看到,有两个望远镜的图标,我们选第二个

弹出下面的对话框,我们点击箭头处那个图标,拖动到我们的游戏窗口中去

拖过去以后,看下图,会出现游戏的标题,我们点确定

这时候 spy++会自动帮我们选择练练看

我们在它选中这一行,点右键—->消息

弹出一个对话框,里面很多乱七八糟的东西一直再滚动,我们先不管他,点箭头指向的那个地方

又弹出一个新的对话框,我们点 消息

在消息界面,我们先点全部清除

这个时候我们发现它一个消息都没选中了,这个时候我们自己选择WM_LBUTTONDOWN和WM_LBUTTONUP 然后点确定

这个时候,我们又回到刚才自动滚动那个界面了,只是他没自动滚动了,我们点下图选择的那把 叉叉 那里 ,点了以后这个界面会变成白色 什么都没有

然后我们到游戏窗口,点下开始,(若想了解更多,请关注我的博客 http://www点dbgpro点com)注意 一定要点一个相对中间的位置

我们再回到spy++ 看看,它拦截到了两条消息,消息的参数是 658 和565 这就是鼠标的位置了,也就是说,我们要把鼠标移动到这个位置

那就简单了,我们在自动开局函数代码如下

void CKyodaiPluginDlg::OnBnClickedCheckstart()

{

HWND hGame = GetGameHwnd();

if (m_checkStart.GetCheck() == BST_CHECKED)

{

int nX = 658;

int nY = 565;

SetCursorPos(nX, nY);

Sleep(100);

mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);

Sleep(50);

mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

}

}

我们用SetCursorPos来移动鼠标,参数是鼠标的位置

mouse_event函数来模拟鼠标点击

然后我们编译运行看看,不能自动点击开始了,并且发现鼠标移动的位置不对,是因为SetCursorPos的坐标是相对于屏幕的,而我们获取到的坐标 是相对于QQ连连看的,所以我们要获取练练看窗口的位置,并加上它的偏移 最终代码如下

void CKyodaiPluginDlg::OnBnClickedCheckstart()

{

HWND hGame = GetGameHwnd();

if (m_checkStart.GetCheck() == BST_CHECKED)

{

CRect rt;

::GetWindowRect(hGame, rt);

int nX = 658 + rt.left;

int nY = 565 + rt.top;

CPoint pt;

GetCursorPos(&pt);//保存当前鼠标的坐标

SetCursorPos(nX, nY);

Sleep(100);

mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);

Sleep(50);

mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

SetCursorPos(pt.x, pt.y);//把鼠标恢复到点开始之前的位置

}

}