重绘闪烁问题总结

来源:互联网 发布:长沙百度seo 编辑:程序博客网 时间:2024/05/17 03:05

重绘闪烁,通常,首先需要怀疑的是WM_ERASEBKGND消息。当一个窗口的背景需要被擦除时,这个消息会被发送。这是因为窗口的绘画通常经历了两个过程 
WM_ERASEBKGND: 清除背景 
WM_PAINT: 在上面绘制内容 

这两个过程让窗体在绘制内容时变得很简单,即:每次当收到WM_PAINT消息时,你知道已经有了一个新画布等待去绘制。然而,画窗口两次(一次是通过WM_ERASEBKGND画背景,另外一次是WM_PAINT)将会导致窗口出现比较糟糕的闪烁现象。只要看看标准的编辑框-打开Windows的写字板并改变窗口大小,就可以看到那种闪烁的效果。 

那么,如何避免窗口背景的重刷呢?有如下两种方法: 
1、设置窗口背景刷子为NULL(当注册Windows类时,设置WNDCLASS结构中的hbrBackground成员为零) 
2、在WM_ERASEBKGND消息处理时 返回非零值 
以上任何一种方法都可以阻止WM_ERASEBKGND 消息去清除窗口。其中,第二个方案的通常可以以如下代码实现: 
case WM_ERASEBKGND:
return 1; 

3、当你标记窗口内容无效并试图更新时,还有如下办法可以防止WM_ERASEBKGND消息:InvalidateRect函数的最后一个参数可以指明在下一次窗口重画时,是否窗口的部分背景会被重刷。将该参数置为False可以防止当窗口需要重画时系统发出WM_ERASEBKGND消息。 
InvalidateRect(hwnd, &rect, FALSE); 

4、剪切子窗体 属性中的Clip children  Clip Sibling 兄弟姐妹窗口
有时,闪烁的原因是因为当重画时,父窗体没有剪切其子窗体区域。这样的结果导致,整个父窗口内容被重画,而子窗体又被显示在了上面(造成闪烁)。这个可以通过在父窗体上设置WS_CLIPCHILDREN 来解决。当这个标志被设置时,被子窗体占据的任何区域将会被排除在更新区域外。因此,即使你尝试在子窗体所在的位置上绘制(父窗口的内容),BeginPaint中的剪切区域也会阻止其绘制效果。 

5、双缓冲

CRect rt;
    GetClientRect(rt);
    CDC *pDC=GetDC();//最好用CPaintDC,CPaintDC只能在OnPaint函数有效
    CDC MemDC
    CBitmap MemBitmap;
    MemDC.CreateCompatibleDC(pDC);
    if (MemDC)
    {
        MemBitmap.CreateCompatibleBitmap(pDC,rt.right,rt.bottom);
        CBitmap *pOldBit =MemDC.SelectObject(&MemBitmap);
        MemDC.FillSolidRect(rt.left,rt.top,rt.right,rt.bottomRGB(0,0,0));
        RealDraw(&MemDC);    
        pDC->BitBlt(rt.left,rt.top,rt.right,rt.bottom,&MemDC,rt.left,rt.top,SRCCOPY);
        MemDC.SelectObject(pOldBit);
        MemBitmap.DeleteObject();
        MemDC.DeleteDC();
    }
    ReleaseDC(pDC);    

6、不该画的时候一定不要画

0 0
原创粉丝点击