双缓冲方法解决屏幕刷新闪烁的问题
2011-10-31 13:21
381 查看
双缓冲方法解决屏幕刷新闪烁的问题
2009年02月24日 星期二 16:12
2009年02月24日 星期二 16:12
http://dev.21tx.com/2005/05/06/11850.html 下载本文所附源代码 关键字 双缓冲 原作者姓名 戚高 介绍 在论坛中经常见到关于刷新时界面闪烁的帖子,如何控制在进行高效绘图时不出现界面闪烁的感觉呢,下文就双缓冲方法进行讲解. 正文 图形为什么会闪烁的原因是:我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。 如何实现双缓冲:在OnDraw(CDC *pDC)中: CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备 MemDC.CreateCompatibleDC(NULL); //这时还不能绘图,因为没有地方画 ^_^ //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小 MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight); //将位图选入到内存显示设备中 //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上 CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); //先用背景色将位图清除干净,这里我用的是白色作为背景 //你也可以用自己应该用的颜色 MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255)); //绘图 MemDC.MoveTo(……); MemDC.LineTo(……); //将内存中的图拷贝到屏幕上进行显示 pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY); //绘图完成后的清理 MemBitmap.DeleteObject(); MemDC.DeleteDC(); 以论坛的一个帖子例子为例来说明一些具体如何解决问题. 帖子那容是: 我想让一个区域动起来, 如何解决窗口刷新时区域的闪烁。 void CJhkljklView::OnDraw(CDC* pDC) { CJhkljklDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here int i; int x[20],y[20]; CPen hPen; POINT w[5]; x[0]=a/100+10; x[1]=a/100+30; x[2]=a/100+80; x[3]=a/100+30; x[4]=a/100+10; y[0]=10; y[1]=10; y[2]=25; y[3]=40; y[4]=40; for (i=0;i<5;i++) { w[i].x=x[i]; w[i].y=y[i]; } //CClientDC dc(this); //hPen=CreatePen(PS_SOLID,1,RGB(255,0,0)); CRgn argn,Brgn; CBrush abrush(RGB(40,30,20)); argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组, pDC->FillRgn(&argn, &abrush); abrush.DeleteObject(); } void CJhkljklView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default InvalidateRect(NULL,true); UpdateWindow(); a+=100; CView::OnTimer(nIDEvent); } int CJhkljklView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here SetTimer(1,10,NULL); return 0; } 利用定时器直接进行10毫秒的屏幕刷新,这样效果会出现不停的闪烁的情况. 解决方法利用双缓冲,首先触发WM_ERASEBKGND,然后修改返回TRUE; 定义变量: CBitmap *m_PBitmapOldBackground ; CBitmap m_bitmapBackground ; CDC m_dcBackground; //绘制背景 if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_hObject == NULL)) { m_dcBackground.CreateCompatibleDC(&dc); m_bitmapBackground.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height()) ; m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_bitmapBackground) ; //DrawMeterBackground(&m_dcBackground, rect); CBrush brushFill, *pBrushOld; // 背景色黑色 brushFill.DeleteObject(); brushFill.CreateSolidBrush(RGB(255, 255, 255)); pBrushOld = m_dcBackground.SelectObject(&brushFill); m_dcBackground.Rectangle(rect); m_dcBackground.SelectObject(pBrushOld); } memDC.BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBackground, 0, 0, SRCCOPY) ; //绘制图形 int i; int x[20],y[20]; CPen hPen; POINT w[5]; x[0]=a/100+10; x[1]=a/100+30; x[2]=a/100+80; x[3]=a/100+30; x[4]=a/100+10; y[0]=10; y[1]=10; y[2]=25; y[3]=40; y[4]=40; for (i=0;i<5;i++) { w[i].x=x[i]; w[i].y=y[i]; } //CClientDC dc(this); //hPen=CreatePen(PS_SOLID,1,RGB(255,0,0)); CRgn argn,Brgn; CBrush abrush(RGB(40,30,20)); argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组, memDC.FillRgn(&argn, &abrush); abrush.DeleteObject(); } 这样编译运行程序就会出现屏幕不闪烁的情况了. |
相关文章推荐
- 双缓冲方法解决屏幕刷新闪烁的问题
- MFC中屏幕刷新闪烁问题解决方法总结
- MFC中屏幕刷新闪烁问题解决方法总结
- wxWidgets学习 - 双缓冲技术解决屏幕闪烁问题
- OpenGL+MFC导致闪烁、不刷新等问题的解决方法
- 双缓冲技术解决屏幕刷新闪烁
- Invalidate函数造成屏幕闪烁问题解决方法
- 屏幕刷新问题解决方法总结
- 屏幕刷新问题解决方法总结
- 用双缓冲技术解决刷新屏幕时的闪屏问题
- C#.net picturebox动画效果,刷新图像的闪烁问题解决方法
- 关于delphi中控件刷新时带来的闪烁问题(gif),转自别人的解决方法描述。
- JavaScript页面刷新与弹出窗口问题解决方法
- C#控件的闪烁问题解决方法总结
- ASP.NET Ajax发布时异步刷新失效的问题解决方法
- C# Winform频繁刷新导致界面闪烁解决方法
- JavaScript页面刷新与弹出窗口问题解决方法
- Windows GDI画图闪烁解决方法 双缓冲技术
- Java写贪吃蛇游戏,用双缓冲重写update方法解决了闪烁问题,有出现了这个问题……
- Y900安装ubuntu kylin16.04屏幕一直闪烁 解决方法