您的位置:首页 > 编程语言 > C语言/C++

双缓冲技术解决屏幕刷新闪烁

2016-12-03 16:13 309 查看
1. 屏幕刷新时产生闪烁的原因

在MFC对话框上画图形,当需要显示新的图形或使原来的图形显示发生变化时,就需要刷新背景,也就是用背景颜色的画刷把背景重新刷一遍,这样就把原来的图形覆盖掉了,然后画上新图形,即可完成图形的刷新显示或动态显示。但是由于背景颜色(一般是白色)与图形颜色之间的反差,在不断的刷新、显示、刷新、显示过程中就会产生闪烁。这里要强调一下,闪烁本质上就是反差,反差越大,闪烁就越厉害。所以总结来说就是,当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint进行重绘,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。

2. 双缓冲技术基本原理

我们知道在我们电脑中,屏幕中显示的东西都会被放在一个称为显示缓存的地方,在通常情况下我们只有一个这样的缓冲区,也就是单缓冲,在单缓冲中任何绘图的过程都会被立即显示在屏幕中,而所谓双缓冲就是再这个显示的缓冲区之外再建立一个不显示的缓冲区,我们所有的绘图都将在这个不显示的缓冲区中进行,只有当一帧都绘制完了之后才会被拷贝到真正的现实缓冲区显示出来,这样中间过程对于最终用户就是不可见的了,那即使是速度比较慢也只会出现停顿而不会有闪烁的现象出现。其基本原理如图2-1所示。



双缓冲技术的基本思路是:

在内存中新建一个临时缓存区;

新建一个位图对象作为画布并绑定临时缓存区,绘图在该缓存区中进行;

当所有图形绘制完成后,把位图对象贴到显示缓存区中(由于是非常规整的内存拷贝,因此速度非常快),因为内存中的图形与屏幕显示图形差别很小,这样看起来就不会闪烁。

3. 双缓冲技术的实现

在OnPaint()函数中的实现代码如下:

void OnPaint()
{
// 获得窗口设备描述表
CPaintDC pDC(this);
// 获取窗口客户区
CRect rect;
GetClientRect(&rect);
//用于缓冲作图的内存DC
CDC dcMem;
//内存中承载临时图象的位图
CBitmap bmp;
//依附窗口DC创建兼容内存DC
dcMem.CreateCompatibleDC(&pDC);
//创建兼容位图
bmp.CreateCompatibleBitmap(&pDC,rect.Width(),rect.Height());
//将位图选择进内存DC
CBitmap *pOldBmp = dcMem.SelectObject(&bmp);
//按原来背景填充客户区,不然会是黑色
dcMem.FillSolidRect(rect,RGB(240, 240, 240));

// 绘制图形
DrawSomething(&dcMem);

// 将内存DC上的图象拷贝到前台
pDC.BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);

dcMem.SelectObject(pOldBmp);
DeleteObject(&bmp);     // 删除位图
dcMem.DeleteDC();       // 删除DC
DeleteObject(pOldBmp); // 删除备份位图
}


然后重载窗口的OnEraseBkgnd()函数,使背景刷变成透明的,实现代码如下:

BOOL OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}


4. 注意事项

当窗口中有控件时,需要把窗口对话框属性Clip Children设置为True,这样在重绘父窗口时就不会刷新子控件的背景,否则界面重绘时控件由于重绘还是会发生闪烁。

5. 参考资料

[1] http://blog.csdn.net/shuilan0066/article/details/6749561

[2] http://blog.csdn.net/acs713/article/details/16359551

[3] http://jingyan.baidu.com/article/4b52d7025f0afefc5c774b12.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  VC++-MFC