重绘闪烁,通常,首先需要怀疑的是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、双缓冲
6、不该画的时候一定不要画