C++实现双缓冲
2015-08-10 22:25
274 查看
首先声明下,这篇资料也是整理别人的资料的基础上,总结来的。
在图形图像处理过程中,双缓冲技术是一种比较常见的技术。窗体在响应WM_PAINT消息时,需要对图像进行绘制处理。如果图像绘制次数过多,重绘过于频繁时,或者当要绘制的对象太复杂,尤其是含有位图时,一般计算机便力不从心了。显示器上就会因为刷新过频或者过慢而闪烁。双缓冲就是解决这种问题的技术。
窗体在刷新前,会首先擦除(OnEraseBkgnd)之前的内容,然后利用背景色填充,再调用绘制代码进行绘制。一擦一填一写,就会形成颜色的反差,当反差过于明显且频繁时,闪烁就来了。擦除绘制需要时间去处理。如果不在窗体上直接绘制,而是在“别的地方”绘制好,然后再直接搬过来,就不会有这种问题了。这就是双缓冲的基本原理。
双缓冲技术中,内存就充当了“别的地方”。双缓冲技术分为五步:
1、在内存中申请缓冲区,创建兼容内存;
2、创建位图,并将位图与缓冲区内存相关联起来;
3、在兼容内存里绘制;
4、将绘制好的位图拷贝到当前设备;
5、释放兼容内存。
具体代码实现如下(这是一个绘制同心圆的例子):
该段代码中已经提供了填充客户区的方法,为了提高绘制效率,可以继承OnEraseBkgnd,然后直接返回true就行。
BOOL Test::OnEraseBkgnd(CDC* pDC)
{
//调用父类的OnEraseBkgnd函数,我们屏蔽此调用
//return CView::OnEraseBkgnd(pDC);
return TRUE;
}
在图形图像处理过程中,双缓冲技术是一种比较常见的技术。窗体在响应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;
}
相关文章推荐
- VS2015编译Libpng1618
- [leetcode-98]Validate Binary Search Tree(c++)
- c语言标准库中字符转换函数和数字转换函数
- 不用库函数,用C语言实现将一整型数字转化为字符串
- C++复制构造函数和赋值符的区别
- 翻译:怎样理解C++ 11中的trivial和standard-layout---An answer from stackoverflow
- c++模版形参(c++ Primer中文第四版)
- 翻译:怎样理解C++中的Aggregate和POD类型---An answer from stackoverflow
- c++中的三种排序,比较基础,因为作为一个编程员总要会几种排序方法
- C++_嵌套类
- c++学习笔记
- 线性表的顺序存储结构
- C语言 - 排序总结
- c++ 使用算法时确保目标区间足够大
- C++/CLI
- C语言 - 经典程序设计100例
- C语言-07-预处理、typedef、static和extern
- C++使用简单的函数指针
- 一起talk C栗子吧(第三十四回:C语言实例--巧用溢出计算最值)
- C/C++ static使用方法注意