亲们,小弟刚接触MFC,做了个小动画类的东西,我用了双缓冲和InvalidateRect了,但为什么还是闪烁呢
下面是OnDraw的代码:
void CMovingBallView::OnDraw(CDC* pDC)
{
CMovingBallDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
//Draw background pic
CRect   rect; 
GetClientRect(&rect); 
pDC-> StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY); 
//get client size;
CRect cRect;
GetClientRect(&cRect);
CString temp;
//遍历存储CBall的vector; 
CClientDC cdc(this);
CString add = _T("  SPACE to Stop,And Click to Add More.\n");
for(int i = 0;i< ballVec.size();i++){
ballVec[i].winH = cRect.bottom;
ballVec[i].winW = cRect.right;
temp.Format(_T("| BALL:(%d , %d) 碰撞次数: %ds |"),ballVec[i].m_Center.x,ballVec[i].m_Center.y,ballVec[i].m_CrashTimes);
add+=temp;
DrawTransBitmap( cdc.GetSafeHdc(),ballVec[i].m_Center.x,ballVec[i].m_Center.y,89,89,    // 目标高度
                   memDC.GetSafeHdc(), 0, 0, ballVec[i].m_TransColor);
}
//Draw Info_text backgroud rect

CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,cRect.right,30);
CDC memRectDC;
memRectDC.CreateCompatibleDC(pDC);
memRectDC.SelectObject(&bmp);
memRectDC.FillSolidRect(0,0,cRect.right,30,RGB(0x08,0x08,0x08)); //蓝色 1874CD
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0x40; //半透明,0为全透明
bf.AlphaFormat = 0;
AlphaBlend(pDC-> GetSafeHdc(),0,0,cRect.right,30,memRectDC.GetSafeHdc(),0,0,cRect.right,30,bf);   


pDC->MoveTo(0,30);
pDC->LineTo(cRect.right,30);
//显示INFO
cdc.SetBkMode(TRANSPARENT);
cdc.DrawText(add,-1,CRect(0,0,cRect.right,30),DT_LEFT + DT_WORDBREAK + DT_END_ELLIPSIS);
}
其中兼容DC是在onCreate里创建的.谢谢大神帮助额

解决方案 »

  1.   


    void CMovingBallView::OnDraw(CDC* pDC)
    {
    CMovingBallDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
    return;
    //Draw background pic
    CRect rect;  
    GetClientRect(&rect);  
    pDC-> StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);  
    //get client size;
    CRect cRect;
    GetClientRect(&cRect);
    CString temp;
    //遍历存储CBall的vector;  
    CClientDC cdc(this);
    CString add = _T(" SPACE to Stop,And Click to Add More.\n");
    for(int i = 0;i< ballVec.size();i++){
    ballVec[i].winH = cRect.bottom;
    ballVec[i].winW = cRect.right;
    temp.Format(_T("| BALL:(%d , %d) 碰撞次数: %ds |"),ballVec[i].m_Center.x,ballVec[i].m_Center.y,ballVec[i].m_CrashTimes);
    add+=temp;
    DrawTransBitmap( cdc.GetSafeHdc(),ballVec[i].m_Center.x,ballVec[i].m_Center.y,89,89, // 目标高度
      memDC.GetSafeHdc(), 0, 0, ballVec[i].m_TransColor);
    }
    //Draw Info_text backgroud rect CBitmap bmp;
    bmp.CreateCompatibleBitmap(pDC,cRect.right,30);
    CDC memRectDC;
    memRectDC.CreateCompatibleDC(pDC);
    memRectDC.SelectObject(&bmp);
    memRectDC.FillSolidRect(0,0,cRect.right,30,RGB(0x08,0x08,0x08)); //蓝色 1874CD
    BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 0x40; //半透明,0为全透明
    bf.AlphaFormat = 0;
    AlphaBlend(pDC-> GetSafeHdc(),0,0,cRect.right,30,memRectDC.GetSafeHdc(),0,0,cRect.right,30,bf);   
    pDC->MoveTo(0,30);
    pDC->LineTo(cRect.right,30);
    //显示INFO
    cdc.SetBkMode(TRANSPARENT);
    cdc.DrawText(add,-1,CRect(0,0,cRect.right,30),DT_LEFT + DT_WORDBREAK + DT_END_ELLIPSIS);
    }
      

  2.   

    重载OnEraseBkgnd, 直接返回,不要调用基类的OnEraseBkgnd.
      

  3.   

    OnEraseBKgnd也已经直接返回true了啊,他是过几秒闪一下,也不是总闪,这是怎么回事啊
      

  4.   

    你需要OnEraseBKgnd直接返回了,但下面的语句:
    pDC-> StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY); 不等于是在刷背景吗?你这哪是什么又缓冲啊!一般来说你做到在OnDraw里面只有一条bitblt语句,就是双缓冲。
    如果你是显示一个动画,肯定不能在OnDraw里面做了,应该在需要完全重绘的时候才调用OnDraw,比如窗口最小化之后又恢复。正确的做法应该是在定时器里面,只对你运动的部分进行擦除与重绘。
      

  5.   

    OnEraseBKgnd也要配合双缓存的。代码中看你一次性画3次,肉眼就能发现了,所以闪烁。
    保证一次性使用
    pDC-> StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);所有工作在memdc中完成了再用上面一句话
      

  6.   

    双缓冲是最后调用pDC把画布显示在客户区,所有的画图动作都在你建立的画布上进行!你有直接画,有在画布上画。
      

  7.   


    谢谢,受教了,再请教您个问题:
      我吧所有东西都在一个缓存memDC里面画,然后再显示到屏幕pDC上,然后我把存放背景的缓存memBkDC画在memDC这个统一的缓存DC上,但是在pDC->bitblt();后怎么显示不出背景呢?
      是不是不可以吧缓存DC绘制到缓存DC再绘制到屏幕呢?
      

  8.   


    弄出来了,看了你的绘制不规则位图里发现我的少了这两句:
    tempBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
    memdc.SelectObject(&tempBitmap);
    但还是不知道为什么要加这个啊.