我最近要完成一个作业,但是遇到了一个窗口闪烁的问题,到论坛上借鉴了很多他人的方法,可还是没有解决,现在再次向大家求助。
问题说明:
1.我的程序框架是单文档类,不过是选用了CFormView类;
2.我的程序中需要一个图片背景,因此我在我的CMyView::OnDraw(CDC* pDC)函数中调用了一个我自己创建的函数picture(),用来画出图片。
        picture()
{
         CWnd *pWnd=GetDlgItem(IDC_STATIC_PIC); //用了一个picture控件,名字即为IDC_STATIC_PIC
CDC *pDC=pWnd->GetDC();
BITMAP bmBackground;
CBitmap bitmapbackground;
bitmapbackground.LoadBitmap(IDB_Convey); //我的图片的资源名是IDB_Convey
bitmapbackground.GetObject(sizeof(bmBackground),&bmBackground);
CDC dcbackground;
dcbackground.CreateCompatibleDC(pDC);
CBitmap *oldbackground=dcbackground.SelectObject(&bitmapbackground);
pDC->BitBlt(0,0,bmBackground.bmWidth,bmBackground.bmHeight,&dcbackground,0,0,SRCCOPY);
dcbackground.DeleteDC();
         }
我试过直接把图片粘到视图里面,它总是浮在最上层,把我的需要的动画作图都覆盖了,所以我就用个函数画图,保证显示顺序。
3.用个红色的小圆来代表工件在传送带上的移动,我用到了一个定时器,工件的绘图区域是rect_workpiece,目标终点区域是
rect_workpiece_aim,并且在OnInitialUpdate()函数中设置
         rect_workpiece.left=415;
rect_workpiece.top=270;
rect_workpiece.bottom=rect_workpiece.top+10;
rect_workpiece.right=rect_workpiece.left+10;
4.定时器里面我用到了Invalidate来刷新窗口区域,因为这个是整体窗口刷新,所以很闪。我试着用过InvalidateRect,不过我这个区域也不是很规则,操作起来也十分麻烦。
附:关键的几个函数:void CMyView::OnStart()  //用了一个按钮,点击运动开始
{
// TODO: Add your control notification handler code here
rect_workpiece_aim.left=415;
rect_workpiece_aim.top=107;
rect_workpiece_aim.right=rect_workpiece_aim.left+10;
rect_workpiece_aim.bottom=rect_workpiece_aim.top+10;
SetTimer(10,50,NULL);
}
void CMyView::OnDraw(CDC* pDC)  //先画图,后画点
{
// TODO: Add your specialized code here and/or call the base class
         picture();
pDC->SelectObject(&yellowbrush);//我创建过一个黄色的笔刷
pDC->Ellipse(rect_workpiece);

}
void CMyView::OnTimer(UINT nIDEvent) 
{
    if(nIDEvent==10)
  {
if((abs(rect_workpiece.left-rect_workpiece_aim.left)>0)||(abs(rect_workpiece.top-rect_workpiece_aim.top)>0))
    {
if((rect_workpiece.left==415)&&(rect_workpiece.top>107)&&(rect_workpiece.top<=270))
{
           rect_workpiece.top--;
  rect_workpiece.right=rect_workpiece.left+10;
  rect_workpiece.bottom=rect_workpiece.top+10;
 Invalidate();
}
    } 
}别的也没有太重要的代码了,可能在高手眼中我的问题很简单,但是您的指点将给我莫大的帮助,这里先谢过了!

解决方案 »

  1.   

    用了一个picture控件 
    你可以直接load进去的 就不用自绘了!!!!
     
      

  2.   

    创建一个内存dc 一个内存位图  把所有的绘图操作都放在 内存dc中 最后一次显示出来  
    LZ可以再网上找 双缓冲的相关资料 很多
    画图可以再OnTimer中画 不一定非得在OnDraw里面
      

  3.   

    To 1楼icefairy:
    首先感谢您的提醒——画图可以再OnTimer中画。我回想起以前做过的类似程序,所以对程序进行了改动,
    在OnDraw函数中只保留了Picture()函数,另外在ontimer函数中我这样处理的:
    void CMyView::OnTimer(UINT nIDEvent) 

        if(nIDEvent==10) 
      { 
         CClientDC dc(this);
         CBrush *pOldBr=dc.SelectObject(&yellowbrush);
    if((abs(rect_workpiece.left-rect_workpiece_aim.left)>0)||(abs(rect_workpiece.top-rect_workpiece_aim.top)>0)) 
        { 
    if((rect_workpiece.left==415)&&(rect_workpiece.top>107)&&(rect_workpiece.top <=270)) 

          rect_workpiece.top--; 
          rect_workpiece.right=rect_workpiece.left+10; 
          rect_workpiece.bottom=rect_workpiece.top+10; 
          dc.Ellipse(rect_workpiece);

        } 
         dc.SelectObject(pOldBr);

    这样修改后屏幕果然不闪烁了,但是紧随而来又出现一个问题,就是这个表示工件的黄色小圆在移动过程中出现了黑色的拖影,在我的背景图片衬托下很是明显。我开始试着从背景图片上解决,首先因为我的窗口一打开就有图片背景,picture()函数要么放在ondraw,要么放在Onpaint()或者onEraseBkground()函数中,无论怎么弄都去不掉那个黑色拖影。
    希望不吝赐教,多谢了!
     
      

  4.   


    LZ 要刷新的东西实在太小了,双缓冲有些不必要。异或笔应该能很好的解决问题pDC->SetROP2()http://baike.baidu.com/view/2317389.htm?fr=ala0_1
      

  5.   

    [Quote=引用 6 楼 joephia 的回复:]
    异或笔应该能很好的解决问题pDC->SetROP2()同样产生了拖影,而且自定义的画笔也不起作用了。
      

  6.   

    你可以在dc.Ellipse(rect_workpiece); 前调用InvalidateRect来重画上一个圆的区域.
    2楼的建议不错.
    另外都画在VIEW上应该不会有问题的,只是一个顺序的问题,可能会闪烁.