在程序需要在界面上移动一个汽车bmp图象,怎么才能做到汽车的无闪烁平滑移动?如何消除汽车移动后的尾巴?(界面背景可能是系统默认的灰色界面,也可能是一张图片,所以消除尾巴时需要恢复到汽车经过前的背景,这个该如何做到?)

解决方案 »

  1.   

    void CCarElement::Display(UDT_State* pudt_State)
    {
    VERIFY(NULL != m_pDC);

    CDC memDC, backDC, newDC;
    backDC.CreateCompatibleDC(m_pDC);
    backDC.SelectObject(m_hBmp);

    newDC.CreateCompatibleDC(m_pDC);
    CBitmap* pBitmap = newDC.SelectObject(&m_Bmp);
    BITMAP bmp;
    m_Bmp.GetBitmap(&bmp);
             //恢复原来位置的背景
    m_pDC->BitBlt(m_OldRECT.left, m_OldRECT.top, m_OldRECT.right - m_OldRECT.left, m_OldRECT.bottom - m_OldRECT.top, &backDC, 0, 0, SRCCOPY);
    if(m_rc.left > 0)
    {
    DeleteObject(m_hBmp);
                      //保存新区域的背景
    m_hBmp = CopyScreenToBitmap(m_pDC, &m_rc);
    }
    //绘图
    m_pDC->StretchBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.top - m_rc.bottom, &newDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

    if(NULL != pBitmap)
    {
    newDC.SelectObject(pBitmap);
    pBitmap->DeleteObject();
    }

    newDC.DeleteDC();
    backDC.DeleteDC();
    memDC.DeleteDC();
    }
    这是我的程序,可是还是达不到效果,请大虾指教!
    其中m_rc为图片新位置,m_OldRECT为前次图片位置,m_hBmp为保存的前次位置的背景,m_Bmp为图片对象
      

  2.   

    CopyScreenToBitmap的问题,m_hBmp应该是用CreateCompatibleBitmap创建出的内存位图,因为汽车的大小是一定的,所以只要创建一个就可以了
      

  3.   

    m_pDC->StretchBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.top - m_rc.bottom, &newDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
    --好像反了,应该是m_rc.bottom - m_rc.top
      

  4.   

    HBITMAP CCarElement::CopyScreenToBitmap(CDC* pDC, LPRECT lpRect)
    {
    HDC hScrDC, hMemDC; 

    HBITMAP hBitmap, hOldBitmap;

    int nX, nY, nX2, nY2;      

    int nWidth, nHeight;      

    VERIFY(NULL != pDC);
    hScrDC = pDC->GetSafeHdc(); VERIFY(NULL != hScrDC);

    hMemDC = CreateCompatibleDC(hScrDC); VERIFY(NULL != hMemDC);

    nX = lpRect->left;

    nY = lpRect->top;

    nX2 = lpRect->right;

    nY2 = lpRect->bottom;

             nWidth = nX2 - nX;

    nHeight = nY2 - nY; if(nHeight < 0)
    nHeight *= -1;

    hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);

    hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);

    hScrDC = NULL;

    if(NULL != hMemDC)
    DeleteDC(hMemDC); if(NULL != hBitmap)
    DeleteObject(hBitmap);

    return hBitmap;
    }
    这是我的CopyScreenToBitmap函数的实现,m_hBmp是HBITMAP类型的
    我还是不太明白大虾的意思,我对图形这块真的不是很清楚,还望多指教!谢谢!
      

  5.   

    to happyparrot(++++禽兽联盟主席-快乐鹦鹉+++++):
    因为我程序里用的是逻辑坐标,所以才这么需要反过来计算区域高度的
      

  6.   

    其中m_rc为图片新位置,m_OldRECT为前次图片位置,m_hBmp为保存的前次位置的背景,m_Bmp为图片对象
    _______________问题出在,你第一次把m_Bmp画在m_pDC上之后,每次保存背景和绘制新背景的时候,它都留在了上面。要保证m_hBmp上没有画上m_Bmp才能消除残像
      

  7.   

    hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
    if(NULL != hBitmap)
    DeleteObject(hBitmap);
    返回的内存位图被你干掉了
      

  8.   

    这样当然不行
    去掉if(NULL != hBitmap)
    DeleteObject(hBitmap);
      

  9.   

    不要考虑太多计算,简单的办法,就是把背景绘制到内存DC上,把汽车按照位置绘制到内存DC上,再把这个内存DC整个绘制到窗口上(每次都这样)。效率低一些,但绝对没问题。
      

  10.   

    to Mackz(在相互):
    我也是这么想的,可是这种方法我一直试验不成功呀,我的试验程序部分代码如下:
    void CMainCtrl::Display(CDC *pDC, RECT rc)
    {
    ASSERT(NULL != pDC); CDC BackgrounDC;
    if(!BackgrounDC.CreateCompatibleDC(pDC))
    return;
             
    BackgrounDC.SelectObject(m_hBitmap); CDC memDC;
    if(!memDC.CreateCompatibleDC(pDC))
    return;
             //将背景绘制在内存DC上
    memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY);
            //将前景图片绘制在内存DC上, m_pElement1为一个CElement实例
    m_pElement1.Display(&memDC, pDC, rc);
             //将内存DC内容绘制在屏幕上
    pDC->BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &memDC, 0, 0, SRCCOPY);
    }//将图片绘制在传递进来的内存DC上,pDestDC为传递进来的内存DC的指针,pSrcDC为屏幕DC
    void CElement::Display(CDC* pDestDC, CDC *pSrcDC, RECT rc)
    {
    ASSERT(NULL != pDestDC && NULL != pSrcDC);
    CDC memDC;
    if(!memDC.CreateCompatibleDC(pSrcDC))
    return;
    memDC.SelectObject(m_Bmp);
    BITMAP bmp;
    m_Bmp.GetBitmap(&bmp);
             //将图片绘制在内存DC上
    pDestDC->BitBlt(rc.left, rc.top, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY); memDC.DeleteDC();
    }
    我的程序看不到效果,不知道在哪里出了问题,请指教!
      

  11.   

    不如用专业的: DirectDraw, 每秒可以达到显卡的刷新频率.
    而且很简单的,MSDN上有详细的例子和说明, 分分钟可以学会.比双缓冲更加明了
      

  12.   

    CDC memDC;
    if(!memDC.CreateCompatibleDC(pDC))
    return;
             //将背景绘制在内存DC上
    memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY);memDC没有对应的缓冲区,需要先临时生成一个跟当前客户区大小一致的CBitmap,并加载后才能使用。
      

  13.   

    谢谢Kerrie,问题解决,给分!