C++实现双缓冲
首先声明下,这篇资料也是整理别人的资料的基础上,总结来的。
在图形图像处理过程中,双缓冲技术是一种比较常见的技术。窗体在响应WM_PAINT消息时,需要对图像进行绘制处理。如果图像绘制次数过多,重绘过于频繁时,或者当要绘制的对象太复杂,尤其是含有位图时,一般计算机便力不从心了。显示器上就会因为刷新过频或者过慢而闪烁。双缓冲就是解决这种问题的技术。
窗体在刷新前,会首先擦除(OnEraseBkgnd)之前的内容,然后利用背景色填充,再调用绘制代码进行绘制。一擦一填一写,就会形成颜色的反差,当反差过于明显且频繁时,闪烁就来了。擦除绘制需要时间去处理。如果不在窗体上直接绘制,而是在“别的地方”绘制好,然后再直接搬过来,就不会有这种问题了。这就是双缓冲的基本原理。
双缓冲技术中,内存就充当了“别的地方”。双缓冲技术分为五步:
1、在内存中申请缓冲区,创建兼容内存;
2、创建位图,并将位图与缓冲区内存相关联起来;
3、在兼容内存里绘制;
4、将绘制好的位图拷贝到当前设备;
5、释放兼容内存。
具体代码实现如下(这是一个绘制同心圆的例子):
CPoint ptCenter; CRect rect,ellipseRect; GetClientRect(&rect); ptCenter = rect.CenterPoint(); CDC dcMem; //用于缓冲作图的内存DC CBitmap cbBmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //申请缓冲区,依附窗口DC创建兼容内存DC cbBmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//创建兼容位图 dcMem.SelectObject(&cbBmp); //将位图选择进内存DC //按原来背景填充客户区,不然会是黑色 dcMem.FillSolidRect(rect,pDC->GetBkColor()); for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象 { ellipseRect.SetRect(ptCenter,ptCenter); ellipseRect.InflateRect(i*10,i*10); dcMem.Ellipse(ellipseRect); } /* //提供下绘制方框、画线等方法 dcMem.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255)); //绘图 dcMem.MoveTo(……); dcMem.LineTo(……); */ pDC->BitBlt(0,0,rect.Width(),rect.Height(), &dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 dcMem.DeleteDC(); //删除DC
该段代码中已经提供了填充客户区的方法,为了提高绘制效率,可以继承OnEraseBkgnd,然后直接返回true就行。
BOOL Test::OnEraseBkgnd(CDC* pDC)
{
//调用父类的OnEraseBkgnd函数,我们屏蔽此调用
//return CView::OnEraseBkgnd(pDC);
return TRUE;
}
言必信,行必果。欢迎访问我的博客。