fangyuanning

统计

最新评论

不用双缓冲实现无闪烁图象

不用双缓冲实现无闪烁图象 收藏
首先说一下产生闪烁的原因,当窗口由于任何原因需要重绘时,总是先用背景色或背景图象将显示区清除,然后才显示图象,这样在短时间内背景色与显示图形交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了,但是会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。

一般的解决方法就是采用双缓冲,创建一幅内存图象,把背景和图片先绘制到该图象,然后把绘制好的该图象显示到窗口,这样就不会产生闪烁,其实就是隐藏了图象的显示过程,原来是在前台,给你看到先在画布上刷上背景,再画上图象,现在是在后台画好了再拿出来给你看。

看起来好象解决方法是需要一次性绘制好图象,其实关键是不能让任何背景及图片在绘制时产生重叠,跟是否一次性绘制没多大关系。电脑的绘制速度还是很快的,不信可以试试把背景刷设置成NULL,这样不会闪烁,然后循环调用BitBlt把一幅小图片铺满整个窗口,虽然是多次绘制,一样不会闪烁,但是如果改变一下循环步长,让图片产生重叠,就会开始闪烁了。

知道了闪烁的原因,不用双缓冲的解决办法就不难找到了,调用ExcludeClipRect,可以排除掉绘制区域,先绘制图片,ExcludeClipRect掉图片的区域,再绘制背景,相当于把一幅挖了一个洞的画布贴到窗口,这样不产生绘制重叠部分,就不会产生闪烁了。

API代码,始终在窗口右下角显示一幅300*200的图片,窗口背景为黑色:

case WM_PAINT:
{
 PAINTSTRUCT ps;
 RECT rc;
 HDC hMemDC;
 
 GetClientRect(hWnd,&rc);
 BeginPaint(hWnd,&ps);
 hMemDC = CreateCompatibleDC(ps.hdc);
 SelectObject(hMemDC,hbmp);
 BitBlt(ps.hdc,rc.right-300,rc.bottom-200,300,200,hMemDC,0,0,SRCCOPY);
 ExcludeClipRect(ps.hdc,rc.right-300,rc.bottom-200,rc.right,rc.bottom);
 FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
 DeleteDC(hMemDC);
 EndPaint(m_hWnd,&ps);
 return 0;
}

有时候因为刷新区域的问题,可能调整窗口但是WM_PAINT的代码不起作用,这时需要响应WM_SIZE消息,通知画面更新一下:
case WM_SIZE:
 InvalidateRect(hWnd,NULL,FALSE);
 break;
 

对于显示多幅图象,这个方法也是适用的,只要每绘制完一幅图象,ExcludeClipRect掉该图象区域就可以,但是注意如果图象有重叠,绘制顺序是反过来的,即盖在最上面的图象需要最先绘制,最后给整个窗口刷上背景就OK了。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ringphone/archive/2007/12/03/1914052.aspx

posted on 2009-07-19 20:18 Pop 阅读(1554) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。