解决MFC贴图实时变化产生闪烁的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chen1083376511/article/details/88192381

           最近在工作中,使用到了MFC绘图的部分。当楼主再次作图时,结果当然是显示窗口不断地闪烁着,非常影响用户的视觉。还记得以前楼主也采用过双缓冲对贴图方面进行过编程,闪烁的问题虽然解决掉了,但是具体是怎么解决的,楼主已记不清楚了。而且现在涉及到很多张照片进行实时变化,即使利用InvalidateRect函数来减少闪烁的区域,一旦这种情况积少成多,也会变成一团糟的画面。

         因此,与其侥幸减少闪烁的次数,还不如彻底解决掉问题的根源,一劳永逸。

采用双缓冲技术:

void CXXX::OnPaint()

{
         CPaintDC dc(this);
         CRect rect;
         this->GetClientRect(&rectt);
         //创建内存DC以及内存画布
         CDC MemDC;
         CBitmap MemBitmap;
         MemDC.CreateCompatibleDC(NULL);
         MemBitmap.CreateCompatibleBitmap(&dc,rec.Width(),rect.Height());
         CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
         MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(0,0,0));

         //画线1
         CPen cPen1(PS_DASH,1,RGB(255,0,0));
         CPen *pOldPen_StationDash=MemDC.SelectObject(&cPen1);
         MemDC.MoveTo(0,0);
         MemDC.LineTo(100,100);
         MemDC.SelectObject(&pOldPen);
         MemDC.SelectObject(pOldPen_StationDash);
         //画线2与画线1的方式一样
         //CPen cPen2...
         //绘图,例如矩形
         //矩形使用画刷
         CBrush brush_WorkStation(RGB(210,105,30));
         CBrush *pOldbrush_WorkStation=MemDC.SelectObject(&brush_WorkStation);
         //矩形的边框
         CPen pen_WorkStation(PS_SOLID,3,RGB(248,248,255));
         CPen *pOldPen_WorkStation=MemDC.SelectObject(&pen_WorkStation);
         //矩形的形状
         MemDC.Rectangle(CRect(0,155,1000,20+155));
         MemDC.SelectObject(pOldPen_WorkStation);
         MemDC.SelectObject(pOldbrush_WorkStation);
         //贴位图,需要再创建一个兼容MemDC的兼容BitSafeMdc
         CDC BitSafeMdc;
         BitSafeMdc.CreateCompatibleDC(&MemDC);
         CBitmap bitmap;
         bitmap.LoadBitmap(IDB_BIT_XXX);
         CBitmap *pOld=BitSafeMdc.SelectObject(&bitmap);
         MemDC.BitBlt(m_nSafeDis1,155,30,30,&BitSafeMdc,0,0,SRCCOPY);
         //MemDC在兼容位图当中贴图或则绘图之后,一次性把一张内存位图复制到当前窗口的客户区域:
         dc.BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);

//释放内存(释放顺序:先释放在内存创建的兼容dc,即BitSafeMdc,再释放兼容位图MemBitmap,最后释放MemDC)
         BitSafeMdc.DeleteDC();
         MemBitmap.DeleteObject();
         MemDC.DeleteDC();      

}

        写完之后,再使用定时器或者采用多线程对图片进行实时变化操作,图像变化时依旧会闪烁。

        不管是Invalidate还是InvalidateRect函数都没有用。

解决办法:

在主调用类要重载基类OnEraseBkgnd(CDC* pDC)函数,在类向导的“消息”一栏添加该函数并重写以下内容:

BOOL CWorkViewBmp::OnEraseBkgnd(CDC* pDC)

{
         // TODO: 在此添加消息处理程序代码和/或调用默认值

         //return CDialogEx::OnEraseBkgnd(pDC);//默认调用父类的函数
           //屏蔽掉父类的函数,具体原因是什么,自行研究
         return false;//由于实时移动图片,必须交给Onpaint函数处理,因此设置为false
 }

即便你再如何频繁调用Invalidate函数,也不会出现闪烁的情况。如果还存在这种问题,那说明我们贴图的方式出了点问题。

    关于其他细节的问题,例如父类的OnEraseBkgnd函数实现的原理是什么,父类对子窗口或者同Z层窗口重叠进行重绘的问题,楼主便不再解释,有兴趣便可自行研究。

参考链接:

双缓冲法解决重绘和闪屏问题:

https://www.cnblogs.com/renyuan/p/3474802.html

MFC双缓冲解决图象闪烁:

https://blog.csdn.net/tiaotiaoyly/article/details/2516235

MFC绘制动态曲线,用双缓冲绘图技术防闪烁:

https://www.cnblogs.com/arxive/p/4911098.html

双缓冲(Double Buffer)原理和使用:

https://www.cnblogs.com/wuguoqiang/p/6649765.html

猜你喜欢

转载自blog.csdn.net/chen1083376511/article/details/88192381