用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
greatws的公告
文章分类
    存档

    原创  QQ找茬辅助工具的制作 收藏

    转载请注明出处http://blog.csdn.net/greatws/archive/2009/05/06/4153247.aspx 

    这段时间GF一直在玩QQ找茬,看了一下,原理很简单,就是找到2附图片的不同之处,那么程序的思路也就很明了了,就是抓图,存入buffer,比较,显示,这么一个过程。闲话不多说了,下面我用MFC来实现它。

    首先先要拿到QQ找茬从窗口的句柄,拿到句柄想咋搞就咋搞,哈哈。当然也可以不要句柄,直接屏幕截图,不过那样就要保证窗口在某个特定的位置,不如句柄来的方便。嗯,还是拿句柄吧,就FindWindow这个函数吧,至于窗口名和类名,用spy++就好啦。

    得到句柄之后,接下来要做的是获得窗口大小及设备DC,然后利用CreateCompatibleBitmap函数,创建与QQ找茬窗口DC兼容的BITMAP对象,针对左右2副图,创建2个,便于以后的比较,然后根据坐标偏移,这个用photoshop可以数出来,利用BitBlt函数复制QQ找茬窗口DC里的位图数据进入创建好的BITMAP对象,然后再把BITMAP中的位图数据复制到内存Buffer中,CopyBMPToBuffer是我对GetDIBits函数做了一下简单的封装,少了几个参数而已。代码如下:

    BOOL CFindDlg::CopyWindowBlt(CWnd *pWndSrc)
    {
        
    if(pWndSrc == NULL)    
        
    {
            
    return FALSE;
        }


        CRect cRect, cRectClient;
        pWndSrc
    ->GetWindowRect(&cRect);
        pWndSrc
    ->GetClientRect(&cRectClient);
        pWndSrc
    ->ClientToScreen(&cRectClient);

        CDC 
    *pSrcDC = NULL;  
        CDC cNewDC;
        CBitmap cBitmapLeft, cBitmapRight;
        BITMAPINFO bi;

        pSrcDC 
    = pWndSrc->GetDC();
        
    //create Compatible Bitmap with the game window
        cBitmapLeft.CreateCompatibleBitmap(pSrcDC, m_nPicWidth, m_nPicHeight);
        cBitmapRight.CreateCompatibleBitmap(pSrcDC, m_nPicWidth, m_nPicHeight);
        cNewDC.CreateCompatibleDC(pSrcDC);
        CBitmap
    * pcOldBitmap = cNewDC.SelectObject(&cBitmapLeft);
        
    //copy bitmap to dc
        cNewDC.BitBlt(00, m_nPicWidth, m_nPicHeight, pSrcDC, 
            m_nLeftPicLeftTopX 
    - (cRectClient.left - cRect.left), 
            m_nLeftPicLeftTopY 
    - (cRectClient.top - cRect.top), SRCCOPY);

        CopyBMPToBuffer(cNewDC.GetSafeHdc(), (HBITMAP)cBitmapLeft.GetSafeHandle(), m_pBufLeft, 
    &bi);

        cNewDC.SelectObject(
    &cBitmapRight);
        cBitmapLeft.DeleteObject();

        cNewDC.BitBlt(
    00, m_nPicWidth, m_nPicHeight, pSrcDC, 
            m_nRightPicLeftTopX 
    - (cRectClient.left - cRect.left), 
            m_nRightPicLeftTopY 
    - (cRectClient.top - cRect.top), SRCCOPY);

        CopyBMPToBuffer(cNewDC.GetSafeHdc(), (HBITMAP)cBitmapRight.GetSafeHandle(), m_pBufRight, 
    &bi);

        cNewDC.SelectObject(pcOldBitmap);
        cBitmapRight.DeleteObject();
        cNewDC.DeleteDC();
        pWndSrc
    ->ReleaseDC(pSrcDC);

        
    return TRUE;
    }

    完成上述工作以后,要比较的位图已经在2块buffer中了,数学建模完成了,已经转化成数学问题了,下面要做的就是比较数组中的数据和显示了。这里我没有用2维数组来做比较,简单的用一下一维就好啦。建立一块新的buffer,全部置为蓝色,这样可以设置alpha透过,以便直接在QQ找茬窗口上面直接显示差异,稍后就会看到效果。比较算法如下,很简单,找到不同处涂为黄色,临近的左右2点图为红色,iDifFlag是为了只涂边缘的点,实际用下来效果不是很好,如果有更好的算法,请告诉我,其中MAKECOLOR是类似COLORREF的一个宏#define MAKECOLOR(r, g, b) (0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff))

            for (int i = iLen - 1; i >= 0; i--)
            
    {
                pdwDstBuf[i] 
    = MAKECOLOR(00255);  //all colors fill blue, in order to set alpha blend
                if ((pdwLeft[i] != pdwRight[i] && iDifFlag == 0||
                    (pdwLeft[i] 
    == pdwRight[i] && iDifFlag == 1))
                
    {

                    pdwDstBuf[i] 
    = MAKECOLOR(2552550);
                    
    if (iDifFlag == 0)
                    
    {
                        
    //first different in one time
                        iDifFlag = 1;
                    }

                    
    else
                    
    {    
                        iDifFlag 
    = 0;
                    }


                    
    //nearby points
                    if (i + 1 < iLen)
                    
    {
                        pdwDstBuf[i 
    + 1= MAKECOLOR(25500);
                    }

                    
    if (i - 1 >= 0)
                    
    {
                        pdwDstBuf[i 
    - 1= MAKECOLOR(25500);
                    }

                    
    if (i + 2 < iLen)
                    
    {
                        pdwDstBuf[i 
    + 2= MAKECOLOR(25500);
                    }

                    
    if (i - 2 >= 0)
                    
    {
                        pdwDstBuf[i 
    - 2= MAKECOLOR(25500);
                    }

                    i 
    -= 2;
                }

            }



    然后呢?最后一步了,就是将比较好的位图显示出来,我这里用到CreateBitmap和CreatePatternBrush这2个函数,然后再利用FillRect刷到窗口中,再把窗口用SetLayeredWindowAttributes设置为蓝色透过,然后移动到QQ找茬窗口上方,这样就OK了。不过CreateBitmap要把图片行序颠倒一下,我懒得转2维数组,直接用偏移搞了一下,OK哈哈。

         for (DWORD i = 0; i < PIC_HEIGHT / 2; i++)
         
    {
            
    for (DWORD j = 0; j < PIC_WIDTH; j++)
            
    {
                 temp 
    = *((DWORD*)pBuf + i * PIC_WIDTH + j);
                 
    *((DWORD*)pBuf + i * PIC_WIDTH + j) = *((DWORD*)pBuf + PIC_WIDTH * (PIC_HEIGHT - 1 - i) + j);
                 
    *((DWORD*)pBuf + PIC_WIDTH * (PIC_HEIGHT - 1 - i) + j) = temp;
            }

         }



        cBM.CreateBitmap(PIC_WIDTH, PIC_HEIGHT, 
    132, pBuf);
        m_cBr.CreatePatternBrush(
    &cBM);
        cBM.DeleteObject();



    最后用SetWindowPos将显示差异的窗口置为顶层窗口。效果图如下:


    目前已知的问题:区域标示很奇怪,是算法的问题,上面我也说过了,有个flag,因为不能保证2附图片的点与点完全不同,所以这样的效果也是显而易见的。
    下载: 可执行程序 (适用于2种找茬游戏,其实就是窗口大小不同)

    By greatws

    发表于 @ 2009年05月06日 00:18:00 | 评论( loading... ) | 编辑| 举报| 收藏

    新一篇:另外的一个blog地址 http://www.cppblog.com/greatws

    • 发表评论
    • 评论内容:
    •  
    Copyright © greatws
    Powered by CSDN Blog