这次的教程大概是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);//把鼠标恢复到点开始之前的位置
}
}