QQ美女找茬辅助器制作
最近,有朋友总要跟我PK QQ美女找茬,无奈在下眼力实在是不如人。不过,咱可是计算机专业的啊,自己找不过他,还不能利用计算机来找吗?嘿嘿,于是开始研究这个辅助工具。
首先,先看看截图:
下面说说制作的方法。我想,大家应该也能想通制作的方法:获取窗口句柄->找到图片(两张)->对比->设置成不同的颜色->显示出来。
过程是很简单的,先看看第一步,获取窗口句柄
- // 获取游戏句柄
- bool CMain::GetGameHandle(void)
- {
- m_pGame = FindWindow(NULL, _T("大家来找茬"));
- if(m_pGame == NULL)
- return false;
- else
- return true;
- }
这里用到了一个FindWindow()函数,函数原型如下
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);
利用窗口名称获取到一个窗口HWND.
然后,很重要的就是获取图片了,把图片要先存入一个缓冲区,以下是代码:
- // 将游戏中位图数据复制到内存中
- bool CMain::CopyPicToBlt(DWORD*& lpvBits, int xSrc, int ySrc, int nWidth, int nHeight)
- {
- HWND hWnd = m_pGame;//主游戏句柄
- HDC hSrcDC=NULL;
- HDC hNewDC;
- //图片格式信息头
- BITMAPINFOHEADER bi;
- bi.biSize = sizeof(BITMAPINFOHEADER);
- bi.biWidth = nWidth;
- bi.biHeight = nHeight;
- bi.biPlanes = 1;
- bi.biBitCount = 32;
- bi.biCompression = BI_RGB;
- bi.biSizeImage = nWidth*nHeight;
- bi.biXPelsPerMeter = 0;
- bi.biYPelsPerMeter = 0;
- bi.biClrUsed = 0;
- bi.biClrImportant = 0;
- HBITMAP pBitmap;
- hSrcDC=GetDC(hWnd);//获取程序DC
- hNewDC = CreateCompatibleDC(hSrcDC);//创建兼容DC
- pBitmap = CreateCompatibleBitmap(hSrcDC, nWidth, nHeight);//设置图大小
- SelectObject(hNewDC, pBitmap); //绑定图片
- //将位图复制到DC中
- BitBlt(hNewDC, 0, 0, nWidth, nHeight, hSrcDC, xSrc, ySrc, SRCCOPY);
- //为图片申请一块内存空间
- if(lpvBits)
- {
- delete[] lpvBits;
- lpvBits=NULL;
- }
- lpvBits = new DWORD[nWidth*nHeight];
- if(!lpvBits)
- {
- return false;
- }
- //将图片数据存储到对应的变量中
- GetDIBits(hNewDC, pBitmap, 0, (UINT)m_nPicHeight, lpvBits, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
- DeleteObject(pBitmap);
- DeleteDC(hNewDC);
- return true;
- }
这里,要先简单说下BMP图片的知识。BMP图片其实在计算机里也是以二进制的方式存储的(任何文件其实都是),这样,我们用一个DWORD指针来作为BUFFER,方便比较。通过这个函数,就把窗口中(xSrc, ySrc)位置的(nWidth, nHeight)大小的位图存储到了lpvBits指向的缓冲区了,以后直接比较两个缓冲区的内容即可。
- // 比较两个图片
- void CMain::CompareBMP(DWORD*& pBuffer, DWORD* pLeft, DWORD* pRight)
- {
- if(!pBuffer)
- {
- delete[] pBuffer;
- pBuffer=NULL;
- }
- pBuffer = new DWORD[m_nPicWidth*m_nPicHeight];
- //比较两幅图,数据相同的设置为白色,不同的为红色。
- for (DWORD i = 0; i < (DWORD)m_nPicWidth * m_nPicHeight; i++)
- {
- if(pLeft[i] != pRight[i])
- pBuffer[i] = RGB(0,0,255);
- else
- pBuffer[i] = RGB(255,255,255);
- }
- //SaveBMP(pBuffer, _T("d://result1.bmp") );
- //转换图片数据,使图片按正常顺序显示。(BMP格式与窗口图像存放竖坐标相反)
- int width = m_nPicWidth;
- for (DWORD i = 0; i < (DWORD)(m_nPicHeight / 2); i++)
- {
- for (DWORD j = 0; j < (DWORD)width; j++)
- {
- DWORD temp;
- temp = *(pBuffer + i * width + j);
- *(pBuffer + i * width + j) = *(pBuffer + width * (m_nPicHeight - 1 - i) + j);
- *(pBuffer + width * (m_nPicHeight - 1 - i) + j) = temp;
- }
- }
- //SaveBMP(pBuffer, _T("d://result2.bmp") );
- if(pLeft)
- {
- delete[] pLeft;
- pLeft = NULL;
- }
- if(pRight)
- {
- delete[] pRight;
- pRight = NULL;
- }
- }
最后通过上面的来比较图片。当然,这个算法是最简单的算法,就是利用循环,按顺序比较,再将结果填充到一个新的缓冲区里,把原先的两张图片缓冲区内内容清除掉
然后,就是显示出来了,首先要先创建一个半透明的对话框
- // 点击查找后
- void CFindFaultDlg::FindFault(void)
- {
- if(!m_GameMain.GetGameHandle())
- {
- MessageBox( _T("请先打开'QQ美女找茬'游戏"), _T("温情提示"));
- return;
- }
- DWORD* pBuffer=NULL;
- //创建一个对话框,用于显示找茬游戏中两幅图的不同点
- if(m_pDlg)
- m_pDlg->DestroyWindow();
- m_GameMain.FindingFault(pBuffer);
- m_pDlg = new CDialog();
- if(m_pDlg)
- {
- if(!m_pDlg->Create(IDD_DLGSHOW, this))
- {
- MessageBox( _T("对话框初始化失败"), _T("温情提示") );
- return ;
- }
- //利用SetLayeredWindowAttributes设置窗口透明。
- //自带的SDK不支持,需要更新才能直接使用这个函数。
- //SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED);
- //SetLayeredWindowAttributes(this->m_hWnd,0,128,2);
- //
- //动态的从User32.dll中取得SetLayeredWindowAttributes函数地址。WS_EX_LAYERED = 0x80000
- SetWindowLong(m_pDlg->GetSafeHwnd(),GWL_EXSTYLE, GetWindowLong(m_pDlg->GetSafeHwnd(),GWL_EXSTYLE)^0x80000| WS_EX_TRANSPARENT);
- HINSTANCE hInst=LoadLibrary(_T("User32.DLL"));
- if(hInst)
- {
- typedef BOOL (WINAPI * MYFUNC)(HWND,COLORREF,BYTE,DWORD);
- MYFUNC fun=NULL;
- //取得SetLayeredWindowAttributes函数指针
- fun=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");
- if(fun)
- fun(m_pDlg->GetSafeHwnd(),0,128,2);
- FreeLibrary(hInst);
- }
- //移动该对话框窗口,置顶,覆盖找茬游戏界面中右边的那幅图。
- CRect rect;
- CWnd* pGameWnd = FindWindow(NULL, _T("大家来找茬"));
- pGameWnd->GetClientRect(&rect);
- pGameWnd->ClientToScreen(&rect);
- if(!m_pDlg->SetWindowPos(&wndTopMost, rect.left + m_ShowOffsetX, rect.top + m_ShowOffsetY,
- 497, 448, SWP_SHOWWINDOW))
- {
- MessageBox(_T("设置对话框失败!"), _T("温情提示"));
- return;
- }
- }
- else
- {
- MessageBox(_T("创建对话框对象失败!"), _T("温情提示"));
- return;
- }
- //显示不同
- CDC* pShow = m_pDlg->GetDC();
- ShowFault(pShow,pBuffer);
- //m_GameMain.SaveBMP(pBuffer, _T("D://result3.bmp") );
- if(pBuffer)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- }
上面的函数不仅显示了对话框,而且将位置通过SetWindowPos()调整到当前游戏窗口中图片的上方
然后就是把不同的地方显示出来
- // 显示不同的地方
- void CFindFaultDlg::ShowFault(CDC* pDC, DWORD* pBuffer)
- {
- CBitmap bm;
- bm.CreateBitmap(m_GameMain.GetPicFrame().x,m_GameMain.GetPicFrame().y,1,32, pBuffer);
- //bm.LoadBitmap(_T("I://result.bmp"));
- CBrush brush;
- brush.CreatePatternBrush(&bm);
- CBrush* pOldBrush = (CBrush*)pDC->SelectObject(&brush);
- pDC->FillRect(&CRect(0, 0, m_GameMain.GetPicFrame().x,m_GameMain.GetPicFrame().y),&brush);
- pDC->SelectObject(pOldBrush);
- brush.DeleteObject();
- bm.DeleteObject();
- ReleaseDC(pDC);
- }
这里是用刚才比较结束后的缓冲区内容的位图信息创建了一个画刷brush,然后用该画刷填充整个窗口,这样就结束了。
后记:通过制作这个小小的辅助工具,了解了获取句柄的方法,遇到了许多问题,比如32位位图和24位位图就有很大区别。
还有半透明窗口的显示。而且,最后遇到了一个很诡异的问题,这个程序到这里在我自己的电脑上都很正确,可是当我在我家的电脑上使用的时候,就总是在中间多出来一个方块的东西,而且只能显示一次,再点显示也是无效,无奈在家电脑也装上VS来调试,调试的时候也没发现什么问题,该执行的语句都执行了。如果有哪位高手知道这个问题的答案,还望多多指教。顺便说一句,我的系统是Win7,家中的是Vista。
为了解决这个问题,我最后采用了另外一种方法:不是通过截取窗口,而是截取屏幕,结果就正常了。。。
- // 通过截屏来获取图像
- bool CMain::GetPicByCap(DWORD*& lpvbits, int xSrc, int ySrc, int nWidth, int nHeight)
- {
- HWND hWnd = m_pGame; //得到句柄
- HDC hdcScreen;
- HDC hdcWindow;
- HDC hdcMemDC = NULL;
- HBITMAP hbmScreen = NULL;
- BITMAP bmpScreen;
- // Retrieve the handle to a display device context for the client
- // area of the window.
- hdcScreen = GetDC(NULL);
- hdcWindow = GetDC(hWnd);
- hdcMemDC = CreateCompatibleDC(hdcWindow);
- if(!hdcMemDC)
- {
- MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
- goto done;
- }
- // Get the client area for size calculation
- RECT rcClient;
- GetClientRect(hWnd, &rcClient);
- POINT pPos;
- pPos.x = xSrc;
- pPos.y = ySrc;
- ClientToScreen(hWnd, &pPos);//转换坐标
- //This is the best stretch mode
- //SetStretchBltMode(hdcWindow,HALFTONE);
- // Create a compatible bitmap from the Window DC
- hbmScreen = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
- if(!hbmScreen)
- {
- MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
- goto done;
- }
- // Select the compatible bitmap into the compatible memory DC.
- SelectObject(hdcMemDC,hbmScreen);
- // Bit block transfer into our compatible memory DC.
- if(!BitBlt(hdcMemDC,
- 0,0,
- nWidth, nHeight,
- hdcScreen,
- pPos.x, pPos.y,
- SRCCOPY))
- {
- MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
- goto done;
- }
- // Get the BITMAP from the HBITMAP
- GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
- BITMAPFILEHEADER bmfHeader;
- BITMAPINFOHEADER bi;
- bi.biSize = sizeof(BITMAPINFOHEADER);
- bi.biWidth = bmpScreen.bmWidth;
- bi.biHeight = bmpScreen.bmHeight;
- bi.biPlanes = 1;
- bi.biBitCount = 32;
- bi.biCompression = BI_RGB;
- bi.biSizeImage = 0;
- bi.biXPelsPerMeter = 0;
- bi.biYPelsPerMeter = 0;
- bi.biClrUsed = 0;
- bi.biClrImportant = 0;
- DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
- if(lpvbits)
- {
- delete[] lpvbits;
- lpvbits = NULL;
- }
- lpvbits = new DWORD[nWidth*nHeight];
- // Gets the "bits" from the bitmap and copies them into a buffer
- // which is pointed to by lpbitmap.
- GetDIBits(hdcWindow, hbmScreen, 0,
- (UINT)bmpScreen.bmHeight,
- lpvbits,
- (BITMAPINFO *)&bi, DIB_RGB_COLORS);
- //Clean up
- done:
- DeleteObject(hbmScreen);
- ReleaseDC(hWnd, hdcMemDC);
- ReleaseDC(NULL,hdcScreen);
- ReleaseDC(hWnd,hdcWindow);
- return true;
- }
这个是从MSDN上参考而来的。其实很简单,就是用ClientToScreen(hWnd, &pPos);把窗口中的坐标转换为对应的屏幕坐标,其他的和第一个是一样的。
附:
各图片位置,窗口大小等信息,这个找起来很麻烦。。。
m_nPicWidth = 498-1; //左右两副图本身有偏移1个像素,去掉偏移的,只比较共有的部分
m_nPicHeight = 448;
m_nOffsetLeftPicX = 8;
m_nOffsetLeftPicY = 193;
m_nOffsetRightPicX = 516 + 1; //左右两副图本身有偏移1个像素,去掉偏移的,只比较共有的部分
m_nOffsetRightPicY = 193;
QQ美女找茬辅助器制作相关推荐
- 自己写的QQ美女找茬外挂
这里首先说一下原理:利用截屏的 技术,讲当前QQ美女找茬的图片截屏下来,然后分析两幅图片相同位置的像素点,当两个点的差大于某个阀值时,将该点的颜色设置为红色. 下面根据 源码具体讲解: 1.首 ...
- 也谈QQ美女找茬外挂的编写
不久前发表在首页的QQ美女找茬(外挂)学习笔记一文让我深受启发,我看了该文章后,也自己动手实现了一个外挂,效果挺不错的.请看截图: 从图中可以看出,我没有让结果显示在原游戏窗口中,而是显示在了外挂窗口 ...
- java 版qq美女找茬助手
原理:截图+图片比较,调用第三方库实现全局热键 首先是截图部分 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();BufferedIm ...
- QQ美女找茬工具,大家测试一下,看看有没有问题
h t t p s : / / p a n . b a i d u . c o m / s / 1 c 1 1 4 1 Z a 这是下载地址,在win7 32和win10 64位系统测试没问题.另外此 ...
- QQ找茬辅助工具 C#
昨天晚上用C#做了一个QQ游戏"找茬"辅助工具.这个不能算是一个外挂工具,因为不涉及到服务器和客户端的问题,只涉及到图像处理的知识.目前只是实现了基本的功能,但是已经够用了,玩了几 ...
- QQ找茬辅助工具的制作
QQ找茬辅助工具的制作 转载请注明出处:http://www.cppblog.com/greatws/archive/2009/05/05/81996.html 这段时间GF一直在玩QQ找茬,看了一下 ...
- QQ游戏美女找茬外挂
前段时间看到别人玩QQ游戏,美女来找茬,突然之间想到自己可以做个小外挂,自动比较两幅图,把不同之处标出来.软件自动化测试和开发简单的游戏外挂很相似.都是控制UI,然后模拟键盘和鼠标操作 思路: 1. ...
- QQ找茬辅助工具的制作[转]
出处:http://www.cppblog.com/greatws/archive/2009/05/05/81996.html 这段时间GF一直在玩QQ找茬,看了一下,原理很简单,就是找到2附图片的不 ...
- 跟我学 编写QQ找茬辅助1 -原创文章
今天把完美日志更新一下打算早点睡觉的. 被朋友拉着玩了一下QQ找茬..高手大有人在啊..很是悲惨.. 朋友痛恨的说.不行,要找外挂玩玩..百度一下,也还有不少..对于 ...
- 才子佳人与QQ游戏美女找茬外挂实现
"我未成名君未嫁,可能俱是不如人?",唐朝才子罗隐一生怀才不遇,屡考未中,话说当初以寒士身份赴举,路过锺陵,即今天的江西进贤,结识了当地的一名乐营女子云英,郎才女貌,把酒言欢,一醉 ...
最新文章
- Review: Maximum Energy Efficiency Tracking for Wireless Power Transfer Systems
- SilverLight学习笔记--建立Silverlight自定义控件(1)--外观设计
- BZOJ4300 绝世好题(动态规划)
- Example - RCP Text Editor
- 知识付费为何从一个“圈粉”的事业变成一个“骗粉”的勾当?
- 3DSlicer22:Module-ExtensionWizard Build Install
- jfinal上传文件
- 【每日一题】5月7日题目精讲 「火」皇家烈焰
- 项目需求:基于微信平台的拼团活动系统
- Vue学习笔记之11-slot插槽
- 6.1倒计时锁(Countdown Latches)
- docker中运行mysql5.7,使用navicat链接报错10061/10060
- 个所税服务器没有企业信息,【重要】企业纳税申报一定要看进来!
- Spring中的refresh()
- MATLAB 插值放大
- 时势造英雄之策略模式
- 分享一个英语听力资源下载网站
- WMS系统运用波次拣货原理
- 选择 FreeBSD 而不是 Linux 的技术性原因
- Kotlin之Set和Get