最近,有朋友总要跟我PK QQ美女找茬,无奈在下眼力实在是不如人。不过,咱可是计算机专业的啊,自己找不过他,还不能利用计算机来找吗?嘿嘿,于是开始研究这个辅助工具。

首先,先看看截图:

下面说说制作的方法。我想,大家应该也能想通制作的方法:获取窗口句柄->找到图片(两张)->对比->设置成不同的颜色->显示出来。

过程是很简单的,先看看第一步,获取窗口句柄

Code:
  1. // 获取游戏句柄
  2. bool CMain::GetGameHandle(void)
  3. {
  4. m_pGame = FindWindow(NULL, _T("大家来找茬"));
  5. if(m_pGame == NULL)
  6. return false;
  7. else
  8. return true;
  9. }

这里用到了一个FindWindow()函数,函数原型如下

HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);

利用窗口名称获取到一个窗口HWND.

然后,很重要的就是获取图片了,把图片要先存入一个缓冲区,以下是代码:

Code:
  1. // 将游戏中位图数据复制到内存中
  2. bool CMain::CopyPicToBlt(DWORD*& lpvBits,  int xSrc, int ySrc, int nWidth, int nHeight)
  3. {
  4. HWND hWnd = m_pGame;//主游戏句柄
  5. HDC hSrcDC=NULL;
  6. HDC hNewDC;
  7. //图片格式信息头
  8. BITMAPINFOHEADER   bi;
  9. bi.biSize = sizeof(BITMAPINFOHEADER);
  10. bi.biWidth = nWidth;
  11. bi.biHeight = nHeight;
  12. bi.biPlanes = 1;
  13. bi.biBitCount = 32;
  14. bi.biCompression = BI_RGB;
  15. bi.biSizeImage = nWidth*nHeight;
  16. bi.biXPelsPerMeter = 0;
  17. bi.biYPelsPerMeter = 0;
  18. bi.biClrUsed = 0;
  19. bi.biClrImportant = 0;
  20. HBITMAP pBitmap;
  21. hSrcDC=GetDC(hWnd);//获取程序DC
  22. hNewDC = CreateCompatibleDC(hSrcDC);//创建兼容DC
  23. pBitmap = CreateCompatibleBitmap(hSrcDC, nWidth, nHeight);//设置图大小
  24. SelectObject(hNewDC, pBitmap);  //绑定图片
  25. //将位图复制到DC中
  26. BitBlt(hNewDC, 0, 0, nWidth, nHeight, hSrcDC, xSrc, ySrc, SRCCOPY);
  27. //为图片申请一块内存空间
  28. if(lpvBits)
  29. {
  30. delete[] lpvBits;
  31. lpvBits=NULL;
  32. }
  33. lpvBits = new DWORD[nWidth*nHeight];
  34. if(!lpvBits)
  35. {
  36. return false;
  37. }
  38. //将图片数据存储到对应的变量中
  39. GetDIBits(hNewDC, pBitmap, 0, (UINT)m_nPicHeight, lpvBits, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
  40. DeleteObject(pBitmap);
  41. DeleteDC(hNewDC);
  42. return true;
  43. }

这里,要先简单说下BMP图片的知识。BMP图片其实在计算机里也是以二进制的方式存储的(任何文件其实都是),这样,我们用一个DWORD指针来作为BUFFER,方便比较。通过这个函数,就把窗口中(xSrc, ySrc)位置的(nWidth, nHeight)大小的位图存储到了lpvBits指向的缓冲区了,以后直接比较两个缓冲区的内容即可。

Code:
  1. // 比较两个图片
  2. void CMain::CompareBMP(DWORD*& pBuffer, DWORD* pLeft, DWORD* pRight)
  3. {
  4. if(!pBuffer)
  5. {
  6. delete[] pBuffer;
  7. pBuffer=NULL;
  8. }
  9. pBuffer = new DWORD[m_nPicWidth*m_nPicHeight];
  10. //比较两幅图,数据相同的设置为白色,不同的为红色。
  11. for (DWORD i = 0; i < (DWORD)m_nPicWidth * m_nPicHeight; i++)
  12. {
  13. if(pLeft[i] != pRight[i])
  14. pBuffer[i] = RGB(0,0,255);
  15. else
  16. pBuffer[i] = RGB(255,255,255);
  17. }
  18. //SaveBMP(pBuffer, _T("d://result1.bmp") );
  19. //转换图片数据,使图片按正常顺序显示。(BMP格式与窗口图像存放竖坐标相反)
  20. int width = m_nPicWidth;
  21. for (DWORD i = 0; i < (DWORD)(m_nPicHeight / 2); i++)
  22. {
  23. for (DWORD j = 0; j < (DWORD)width; j++)
  24. {
  25. DWORD temp;
  26. temp = *(pBuffer + i * width + j);
  27. *(pBuffer + i * width + j) = *(pBuffer + width * (m_nPicHeight - 1 - i) + j);
  28. *(pBuffer + width * (m_nPicHeight - 1 - i) + j) = temp;
  29. }
  30. }
  31. //SaveBMP(pBuffer, _T("d://result2.bmp") );
  32. if(pLeft)
  33. {
  34. delete[] pLeft;
  35. pLeft = NULL;
  36. }
  37. if(pRight)
  38. {
  39. delete[] pRight;
  40. pRight = NULL;
  41. }
  42. }

最后通过上面的来比较图片。当然,这个算法是最简单的算法,就是利用循环,按顺序比较,再将结果填充到一个新的缓冲区里,把原先的两张图片缓冲区内内容清除掉

然后,就是显示出来了,首先要先创建一个半透明的对话框

Code:
  1. // 点击查找后
  2. void CFindFaultDlg::FindFault(void)
  3. {
  4. if(!m_GameMain.GetGameHandle())
  5. {
  6. MessageBox( _T("请先打开'QQ美女找茬'游戏"), _T("温情提示"));
  7. return;
  8. }
  9. DWORD* pBuffer=NULL;
  10. //创建一个对话框,用于显示找茬游戏中两幅图的不同点
  11. if(m_pDlg)
  12. m_pDlg->DestroyWindow();
  13. m_GameMain.FindingFault(pBuffer);
  14. m_pDlg = new CDialog();
  15. if(m_pDlg)
  16. {
  17. if(!m_pDlg->Create(IDD_DLGSHOW, this))
  18. {
  19. MessageBox( _T("对话框初始化失败"), _T("温情提示") );
  20. return ;
  21. }
  22. //利用SetLayeredWindowAttributes设置窗口透明。
  23. //自带的SDK不支持,需要更新才能直接使用这个函数。
  24. //SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED);
  25. //SetLayeredWindowAttributes(this->m_hWnd,0,128,2);
  26. //
  27. //动态的从User32.dll中取得SetLayeredWindowAttributes函数地址。WS_EX_LAYERED = 0x80000
  28. SetWindowLong(m_pDlg->GetSafeHwnd(),GWL_EXSTYLE, GetWindowLong(m_pDlg->GetSafeHwnd(),GWL_EXSTYLE)^0x80000| WS_EX_TRANSPARENT);
  29. HINSTANCE hInst=LoadLibrary(_T("User32.DLL"));
  30. if(hInst)
  31. {
  32. typedef BOOL  (WINAPI * MYFUNC)(HWND,COLORREF,BYTE,DWORD);
  33. MYFUNC fun=NULL;
  34. //取得SetLayeredWindowAttributes函数指针
  35. fun=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");
  36. if(fun)
  37. fun(m_pDlg->GetSafeHwnd(),0,128,2);
  38. FreeLibrary(hInst);
  39. }
  40. //移动该对话框窗口,置顶,覆盖找茬游戏界面中右边的那幅图。
  41. CRect rect;
  42. CWnd* pGameWnd = FindWindow(NULL, _T("大家来找茬"));
  43. pGameWnd->GetClientRect(&rect);
  44. pGameWnd->ClientToScreen(&rect);
  45. if(!m_pDlg->SetWindowPos(&wndTopMost, rect.left + m_ShowOffsetX, rect.top + m_ShowOffsetY,
  46. 497, 448, SWP_SHOWWINDOW))
  47. {
  48. MessageBox(_T("设置对话框失败!"), _T("温情提示"));
  49. return;
  50. }
  51. }
  52. else
  53. {
  54. MessageBox(_T("创建对话框对象失败!"), _T("温情提示"));
  55. return;
  56. }
  57. //显示不同
  58. CDC* pShow = m_pDlg->GetDC();
  59. ShowFault(pShow,pBuffer);
  60. //m_GameMain.SaveBMP(pBuffer, _T("D://result3.bmp") );
  61. if(pBuffer)
  62. {
  63. delete[] pBuffer;
  64. pBuffer = NULL;
  65. }
  66. }

上面的函数不仅显示了对话框,而且将位置通过SetWindowPos()调整到当前游戏窗口中图片的上方

然后就是把不同的地方显示出来

Code:
  1. // 显示不同的地方
  2. void CFindFaultDlg::ShowFault(CDC* pDC, DWORD* pBuffer)
  3. {
  4. CBitmap bm;
  5. bm.CreateBitmap(m_GameMain.GetPicFrame().x,m_GameMain.GetPicFrame().y,1,32, pBuffer);
  6. //bm.LoadBitmap(_T("I://result.bmp"));
  7. CBrush brush;
  8. brush.CreatePatternBrush(&bm);
  9. CBrush* pOldBrush = (CBrush*)pDC->SelectObject(&brush);
  10. pDC->FillRect(&CRect(0, 0, m_GameMain.GetPicFrame().x,m_GameMain.GetPicFrame().y),&brush);
  11. pDC->SelectObject(pOldBrush);
  12. brush.DeleteObject();
  13. bm.DeleteObject();
  14. ReleaseDC(pDC);
  15. }

这里是用刚才比较结束后的缓冲区内容的位图信息创建了一个画刷brush,然后用该画刷填充整个窗口,这样就结束了。

后记:通过制作这个小小的辅助工具,了解了获取句柄的方法,遇到了许多问题,比如32位位图和24位位图就有很大区别。

还有半透明窗口的显示。而且,最后遇到了一个很诡异的问题,这个程序到这里在我自己的电脑上都很正确,可是当我在我家的电脑上使用的时候,就总是在中间多出来一个方块的东西,而且只能显示一次,再点显示也是无效,无奈在家电脑也装上VS来调试,调试的时候也没发现什么问题,该执行的语句都执行了。如果有哪位高手知道这个问题的答案,还望多多指教。顺便说一句,我的系统是Win7,家中的是Vista。

为了解决这个问题,我最后采用了另外一种方法:不是通过截取窗口,而是截取屏幕,结果就正常了。。。

Code:
  1. // 通过截屏来获取图像
  2. bool CMain::GetPicByCap(DWORD*& lpvbits, int xSrc, int ySrc, int nWidth, int nHeight)
  3. {
  4. HWND hWnd = m_pGame;    //得到句柄
  5. HDC hdcScreen;
  6. HDC hdcWindow;
  7. HDC hdcMemDC = NULL;
  8. HBITMAP hbmScreen = NULL;
  9. BITMAP bmpScreen;
  10. // Retrieve the handle to a display device context for the client
  11. // area of the window.
  12. hdcScreen = GetDC(NULL);
  13. hdcWindow = GetDC(hWnd);
  14. hdcMemDC = CreateCompatibleDC(hdcWindow);
  15. if(!hdcMemDC)
  16. {
  17. MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
  18. goto done;
  19. }
  20. // Get the client area for size calculation
  21. RECT rcClient;
  22. GetClientRect(hWnd, &rcClient);
  23. POINT pPos;
  24. pPos.x = xSrc;
  25. pPos.y = ySrc;
  26. ClientToScreen(hWnd, &pPos);//转换坐标
  27. //This is the best stretch mode
  28. //SetStretchBltMode(hdcWindow,HALFTONE);
  29. // Create a compatible bitmap from the Window DC
  30. hbmScreen = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
  31. if(!hbmScreen)
  32. {
  33. MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
  34. goto done;
  35. }
  36. // Select the compatible bitmap into the compatible memory DC.
  37. SelectObject(hdcMemDC,hbmScreen);
  38. // Bit block transfer into our compatible memory DC.
  39. if(!BitBlt(hdcMemDC,
  40. 0,0,
  41. nWidth, nHeight,
  42. hdcScreen,
  43. pPos.x, pPos.y,
  44. SRCCOPY))
  45. {
  46. MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
  47. goto done;
  48. }
  49. // Get the BITMAP from the HBITMAP
  50. GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
  51. BITMAPFILEHEADER   bmfHeader;
  52. BITMAPINFOHEADER   bi;
  53. bi.biSize = sizeof(BITMAPINFOHEADER);
  54. bi.biWidth = bmpScreen.bmWidth;
  55. bi.biHeight = bmpScreen.bmHeight;
  56. bi.biPlanes = 1;
  57. bi.biBitCount = 32;
  58. bi.biCompression = BI_RGB;
  59. bi.biSizeImage = 0;
  60. bi.biXPelsPerMeter = 0;
  61. bi.biYPelsPerMeter = 0;
  62. bi.biClrUsed = 0;
  63. bi.biClrImportant = 0;
  64. DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
  65. if(lpvbits)
  66. {
  67. delete[] lpvbits;
  68. lpvbits = NULL;
  69. }
  70. lpvbits = new DWORD[nWidth*nHeight];
  71. // Gets the "bits" from the bitmap and copies them into a buffer
  72. // which is pointed to by lpbitmap.
  73. GetDIBits(hdcWindow, hbmScreen, 0,
  74. (UINT)bmpScreen.bmHeight,
  75. lpvbits,
  76. (BITMAPINFO *)&bi, DIB_RGB_COLORS);
  77. //Clean up
  78. done:
  79. DeleteObject(hbmScreen);
  80. ReleaseDC(hWnd, hdcMemDC);
  81. ReleaseDC(NULL,hdcScreen);
  82. ReleaseDC(hWnd,hdcWindow);
  83. return true;
  84. }

这个是从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美女找茬辅助器制作相关推荐

  1. 自己写的QQ美女找茬外挂

    这里首先说一下原理:利用截屏的 技术,讲当前QQ美女找茬的图片截屏下来,然后分析两幅图片相同位置的像素点,当两个点的差大于某个阀值时,将该点的颜色设置为红色. 下面根据 源码具体讲解:     1.首 ...

  2. 也谈QQ美女找茬外挂的编写

    不久前发表在首页的QQ美女找茬(外挂)学习笔记一文让我深受启发,我看了该文章后,也自己动手实现了一个外挂,效果挺不错的.请看截图: 从图中可以看出,我没有让结果显示在原游戏窗口中,而是显示在了外挂窗口 ...

  3. java 版qq美女找茬助手

    原理:截图+图片比较,调用第三方库实现全局热键 首先是截图部分 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();BufferedIm ...

  4. 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位系统测试没问题.另外此 ...

  5. QQ找茬辅助工具 C#

    昨天晚上用C#做了一个QQ游戏"找茬"辅助工具.这个不能算是一个外挂工具,因为不涉及到服务器和客户端的问题,只涉及到图像处理的知识.目前只是实现了基本的功能,但是已经够用了,玩了几 ...

  6. QQ找茬辅助工具的制作

    QQ找茬辅助工具的制作 转载请注明出处:http://www.cppblog.com/greatws/archive/2009/05/05/81996.html 这段时间GF一直在玩QQ找茬,看了一下 ...

  7. QQ游戏美女找茬外挂

    前段时间看到别人玩QQ游戏,美女来找茬,突然之间想到自己可以做个小外挂,自动比较两幅图,把不同之处标出来.软件自动化测试和开发简单的游戏外挂很相似.都是控制UI,然后模拟键盘和鼠标操作 思路: 1. ...

  8. QQ找茬辅助工具的制作[转]

    出处:http://www.cppblog.com/greatws/archive/2009/05/05/81996.html 这段时间GF一直在玩QQ找茬,看了一下,原理很简单,就是找到2附图片的不 ...

  9. 跟我学 编写QQ找茬辅助1 -原创文章

    今天把完美日志更新一下打算早点睡觉的.        被朋友拉着玩了一下QQ找茬..高手大有人在啊..很是悲惨..           朋友痛恨的说.不行,要找外挂玩玩..百度一下,也还有不少..对于 ...

  10. 才子佳人与QQ游戏美女找茬外挂实现

    "我未成名君未嫁,可能俱是不如人?",唐朝才子罗隐一生怀才不遇,屡考未中,话说当初以寒士身份赴举,路过锺陵,即今天的江西进贤,结识了当地的一名乐营女子云英,郎才女貌,把酒言欢,一醉 ...

最新文章

  1. Review: Maximum Energy Efficiency Tracking for Wireless Power Transfer Systems
  2. SilverLight学习笔记--建立Silverlight自定义控件(1)--外观设计
  3. BZOJ4300 绝世好题(动态规划)
  4. Example - RCP Text Editor
  5. 知识付费为何从一个“圈粉”的事业变成一个“骗粉”的勾当?
  6. 3DSlicer22:Module-ExtensionWizard Build Install
  7. jfinal上传文件
  8. 【每日一题】5月7日题目精讲 「火」皇家烈焰
  9. 项目需求:基于微信平台的拼团活动系统
  10. Vue学习笔记之11-slot插槽
  11. 6.1倒计时锁(Countdown Latches)
  12. docker中运行mysql5.7,使用navicat链接报错10061/10060
  13. 个所税服务器没有企业信息,【重要】企业纳税申报一定要看进来!
  14. Spring中的refresh()
  15. MATLAB 插值放大
  16. 时势造英雄之策略模式
  17. 分享一个英语听力资源下载网站
  18. WMS系统运用波次拣货原理
  19. 选择 FreeBSD 而不是 Linux 的技术性原因
  20. Kotlin之Set和Get

热门文章

  1. 2017第15届上海国际礼品、赠品及家居用品展览会会刊(参展商名录)
  2. open ai gpt_GPT-3:第一个人工智能?
  3. 自己动手画一个CPU——Logisim,下
  4. Starling MovieClip API
  5. c语言投票系统程序,C语言智能投票系统.doc
  6. 保姆级 nas 服务器搭建手册
  7. mysql 闰年,[MySQL]--gt;查询5天之内过生日的同事中的闰年2月
  8. 知识产权产业化的发展未来
  9. after meet KeyNi liu
  10. Spring ClassPathResource详解