最近在工作中,使用到了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