双缓冲 不错的转一下算是!!
来源:互联网 发布:linux系统安全软件 编辑:程序博客网 时间:2024/05/18 20:49
双缓冲是一种常用的消除屏闪的方法,这段文字,是我本科毕业论中的一小段,用来说明显示原理的,现共享出来,共同交流一下。
在MFC程序中,经常会遇到这样的问题:在客户区内动态绘图,或者客户区被其它窗口遮挡而产生无效区域时,会产生闪烁现象,下面我们来分析一下这个问题。
CView类是由CWnd类继承而来,也就是说,CView类是窗口类,客户区就是一个窗口。在Windows程序中,窗口的的更新是通过处理WM_PAINT消息实现的,在更新之前,MFC程序会先处理WM_ERASEBKGND消息,该消息默认处理函数会使用预定义的画刷刷新窗口,作为背景色,然后WM_PAINT消息处理函数重绘窗口。而MFC程序预定义的用来刷新窗口的画刷是白色(24位色RGB(255,255,255)),所以当动态绘图或重绘窗口时,客户区内是白色和图像交替出现,短时间内出现颜色的反差,由于人眼的视觉暂留作用,速度很快的情况不会看出反差,但是会有闪烁的感觉,这是用户所不能接受的,所以,在这里我们来解决这个问题。
首先,要把系统预定义画刷重绘部分去掉。
在ClassWizard中为CConcaveView类(本系统所用的视图类,由CView类继承而来)添加WM_ERASEBKGND消息处理函数,编辑代码,发现其返回值调用了父类(CView类)的消息处理函数,很显然,用预义定画刷重新刷新窗口的工作是在父类中完成的,故应把函数调用删掉,另外,由于其返回的是BOOL类型,所以返回语句改为return TRUE。
建立另一个缓冲区,并在其中作图。在绘图函数中,定义两个局部变量,其类型为CDC(设备上下文类)和CBitmap(位图类),在MFC程序中,存储器中的图像,一般是存储于位图中,而图像与设备的通信,是在设备上下文对象中完成的,所以,把CBitmap对象调入CDC对象中,就可以在设备上下文中作图了,其实质是在主存储器中作图,还没有写入到显存中。
把主存中的图像拷贝到显存,以显示图像。这步很简单,只要把自定义的设备上下文对像,送给系统预定义的设备上下文对像中即可。
总结其原理,出现闪烁的原因关键问题就是颜色的反差,消除了反差,闪烁自然就消除。但是双缓冲是有缺点的:
1. 由于两次绘图,运行速度比较慢,在某些追速度的应用中,效果不是很理想。
2. 使用了两倍的缓冲区空间,空间占用比较大,在某些大规模计算的应用中,不是理想首选。
以上就是在Windows程序设计中,双缓冲算法的思想,其实双缓冲只是一种方法,这个概念不只应用在绘图方面,还有数据的传输、数据库等很多地方,下面是代码样例(ADL语言和C++语言)
在文档/视图结构的MFC工程中,视图类有一个成员函数void OnDraw(CDC* pDC),它由Windows客户区刷新消息WM_PAINT消息的处理函数OnPaint所调用,用于处理当前视图的刷新工作。我们的绘图,就是在它中完成的。
前面已经讨论过客户区刷新时的闪烁问题,即双缓冲显示的算法,由上段所述,双缓冲处理消除闪烁的最佳位置,即OnDraw函数。下面将给出OnDraw函数的实现:
BOOL CConcaveView::OnEraseBkgnd(CDC* pDC)
{
// 此函数为CView类中用默认画刷(白刷)刷新客户区函数的重写
//return CView::OnEraseBkgnd(pDC); //注释掉对父类刷新函数的调用,即摒掉了客户区的刷新
return TRUE;
}
void CConcaveView::OnDraw(CDC* pDC)
{
CConcaveDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect; //定义矩形类对象,用于计算客户区大小
CDC dc; //定义新的设置上下文对象,下一步绘图就在这里
CBitmap bitmap; //定义新的位置,实际是一块缓冲区
GetClientRect(&rect); //计算客户区大小
dc.CreateCompatibleDC(NULL); 创建新的DC
bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height()); //创建与当前设备匹配的位图,分配缓冲区空间
dc.SelectObject(&bitmap); //将缓冲区交与新的DC
dc.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255)); //用白色初始化缓冲区颜色
//从此开始,就可以用新定义的dc画图了
int i;
gShowAnnotation(rect,&dc); //显示注解
gShowBitmap(g_currtopo,rect,&dc); //显示范例位图
if(m_nSelect!=ST_REASON||m_listbox.GetCount())
{
for(i=0;i<3;++i)
{
pDoc->m_pCave[i]->Show(&dc); //从文档类中取出所有图形对象,并调用Show方法显示。
}
}
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY); //调用原系统DC的BitBlt方法,将新缓冲区的内容以SRCCOPY(原拷贝)模式复制给原系统DC,此时,图形将出现在屏幕上
bitmap.DeleteObject(); //删除位图,释放空间
dc.DeleteDC(); //删除dc,释放空间
}
- 双缓冲 不错的转一下算是!!
- 不错的文章,转载一下!
- 不错的向下缓冲式菜单特效
- cgi技术, 感觉讲的不错,转一下
- 一个挺不错的网站,参考一下
- 给大家推荐一下不错的博客
- 一个不错的技术博客,记一下
- 不错的下拉菜单,分享一下
- 不错的Android开发资料,收藏一下
- 分享一下不错的源码网站
- 记录一下不错的技术网站
- 有个blog真的不错,算是在网上有了个自己的家
- 呵呵,测试一下,不错不错。
- 学习Exadata时看到的一篇不错的文章,转一下,自己也备忘
- 转的一篇介绍iostat命令的文件非常不错,学习一下
- 给朋友推荐一些歌,也算是简单的整理一下自己机器里的MP3
- GridView 几种使用方法(转) 真的不错,分享一下
- sping security3.1 别人博客写的 看着不错 转一下
- iterator2
- Use Dom4J to Write XML file
- ubuntu8.04分辨率设置
- Use Jdom to Write XML file
- 恢复刚被误删QQ好友的方法
- 双缓冲 不错的转一下算是!!
- 计算机与网络安全总结(第一部分:基本加解密算法)
- 无法在安装新的版本前,为"*"做一个符号链接备份
- USACO算法系列十八——game1
- 使用jplayer来制作音乐播放插件
- 自动生成Makefile的详细过程
- 通过SSIS实现Oracle与Sqlserver数据库间的数据同步,并定时执行同步任务
- Use Jdom to Read XML file
- eclipse中出现Context startup failed due to previous errors错误解决方法