窗口在刷新的时候总是先刷白一下再绘图 视觉上就是闪一下 该怎么办啊?
我已经用了
BOOL CTsylqDlg::OnEraseBkgnd(CDC* pDC) 
{
// TODO: Add your message handler code here and/or call default

//return CDialog::OnEraseBkgnd(pDC);
return TRUE;}但是没有效果  所以我想在初始化窗口的时候设置窗口背景刷的颜色为透明色 该怎么做呢?
或者有没有其他的方法呢? 
谢谢大家~~~!!!!

解决方案 »

  1.   

    解决Windows 程序界面闪烁问题的一些经验
     一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁。
      先来谈谈闪烁产生的原因
      原因一:
      如果熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕
      上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。
      一般显卡的刷新周期是 1/80秒左右,具体数字可以自己设置的。
      这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个
      刷新周期内完成,那么给人的视觉感受就是,先看到只有背景色的图像,然后看到画上内容的图像,
      这样就会感觉闪烁了。
      解决方法:尽量快的输出图像,使输出在一个刷新周期内完成,如果输出内容很多比较慢,那么采用
      内存缓冲的方法,先把要输出的内容在内存准备好,然后一次输出到显存。要知道一次API调用一般可以
      在一个刷新周期内完成。
      对于GDI,用创建内存DC的方法就可以了
      原因二:
      复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父
      窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。
      我们知道父窗口上被子窗口挡住的部分其实没必要重画的
      解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。
      如果同级窗口之间有重叠,那么需要再加上 WS_CLIPSIBLINGS 风格
      原因三:
      有时候需要在窗口上使用一些控件,比如IE,当你的窗口改变大小的时候IE会闪烁,即使你有了WS_CLIPCHILDREN
      也没用。原因在于窗口的类风格有CS_HREDRAW 或者 CS_VREDRAW,这两个风格表示窗口在宽度或者高度变化的时候
      重画,但是这样就会引起IE闪烁
      解决方法:注册窗口类的时候不要使用这两个风格,如果窗口需要在改变大小的时候重画,那么可以在WM_SIZE的时候
      调用RedrawWindow。
      原因四:
      界面上窗口很多,而且改变大小时很多窗口都要移动和改变大小,如果使用MoveWindow或者SetWindowPos两个API来
      改变窗口的大小和位置,由于他们是等待窗口重画完成后才返回,所以过程很慢,这样视觉效果就可能会闪烁。
      解决方法:
      使用以下API来处理窗口移动,BeginDeferWindowPos, DeferWindowPos,EndDeferWindowPos
      先调用 BeginDeferWindowPos 设定需要移动的窗口的个数
      使用DeferWindowPos,来移动窗口,这个API并不真的造成窗口移动
      EndDeferWindowPos 一次性完成所有窗口的大小和位置的改变。
      有个地方要特别注意,要仔细计算清楚要移动多少个窗口,BeginDeferWindowPos设定
      的个数一定要和实际的个数一致,否则在Win9x下,如果实际移动的窗口数多于调用BeginDeferWindowPos
      时设定的个数,可能会造成系统崩溃。在Windows NT系列下不会有这样的问题。 
      

  2.   

    BOOL CTsylqDlg::OnEraseBkgnd(CDC* pDC) 

    // TODO: Add your message handler code here and/or call default 
    pDC->SetBkColor(TRANSPARENT);
    //return CDialog::OnEraseBkgnd(pDC); 
    return TRUE; } 试试
      

  3.   

    楼主两点要说明: 
       1.OnEraseBkgnd响应从主窗口,到CTsylqDlg,层层都要响应到的。
        2.记得绘制的时候采用双缓冲机制。
    这两点是解决你的闪烁的主要方式!
      

  4.   

    估计没办法弄, 那是绘制的机制。
    return false;
    白屏消失,但是你的绘制是在直接覆盖图像的基础上,
    即越抹越黑。
      

  5.   


    CTsylqDlg就是我的主窗口 ... 双缓冲?什么意思啊?
      

  6.   

    首先谢谢楼上各位的提议 但是关于OnEraseBkgnd  我就是在主窗口里面增加的这个消息处理 不管是return false还是return true 都是白色闪一下,Invalidate函数我加在onpaint函数里面试过 不行啊!!还有什么别的办法吗?
      

  7.   

    采用双缓冲机制是正道:
        说白了也就是在内存中画,然后再贴到界面上.您google上搜一下,有许多例子.
      

  8.   


    Invalidate 不能加在OnPaint内的,在其他地方调用触发OnPaint。
    双缓冲的方法就是创建 一个临时DC,把贴图处理的都放入其内处理完毕后
    再贴出到和屏幕显示相关的DC,如: CWindowDC,CClientDC,CPaintDC……
      

  9.   

    这个肯定是要上双缓冲的 上了双缓冲 在OnEraseBkgnd 中renturn false
      

  10.   


    纠正一下,根据MSND的说法,
    重载OnEraseBkgnd ,其内返回值有如下定义:
    返回1(TRUE) 接受WM_ERASEBKGND的消息,但不会进行背景擦除
    返回0(FALSE)接受WM_ERASEBKGND的消息,但  会进行背景擦除并重新绘制背景。
    所以,
    方案1:你要在OnEraseBkgnd 之外的地方,不擦除背景的情况下用Invalidate(0);
    表示区域有效,保证绘制上的位图能完全覆盖上一张作为背景的位图,那样就不会有白屏闪烁的出现,2.方案2: 即大家所说的双缓冲。
      

  11.   

    1.透明窗体关键代码:
            
    BOOL CClarityDlg::OnInitDialog()
    { CPoint point;
    CRgn rgn, tmp;
    CRect rc;
    m_Static.GetWindowRect(&rc);
    rgn.CreateRectRgn(0,0,rc.Width()-1,rc.Height()-1);
    //计算区域
    for(point.x=0;point.x<=rc.Width();point.x++)
    {
    for(point.y=0;point.y<=rc.Height();point.y++)
    {
    if(rc.PtInRect(point))
    {
    tmp.CreateRectRgn(point.x,point.y,point.x+1,point.y+1);
    rgn.CombineRgn(&rgn,&tmp,RGN_XOR);
    tmp.DeleteObject();
    }
    }
    }
    SetWindowRgn((HRGN)rgn,TRUE);
    }