1. 前言
之前有一篇博客记录了如何在MFC的视图窗口上绘制图像,但是在后来的实际运行中出现了难以忍受的显示区域闪烁现象。产生这样问题的原因是频繁刷新视图窗口,且在当绘图操作复杂度越来越高的情况下越严重。在这样的情况下就要使用双缓存技术来缓解绘图区域闪烁的情况。所谓双缓存技术就是:使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。
基于这样的操作不是直接操作绘图区域,而是操作内存中绘图,因而从人眼看到的画面角度闪烁会缓解很多。
2. 双缓存技术实现
在这里我就直接贴出双缓存实现的代码:
//绘制背景色
CClientDC dc(this);
CRect *wndrect = new CRect;
GetClientRect(wndrect);
if (pDC == nullptr)
{
pDC = GetDC();
}
CDC dcMem; //用于缓冲作图的内存DC
CBitmap bmp; //内存中承载临时图象的位图
dcMem.CreateCompatibleDC(NULL); //依附窗口DC创建兼容内存DC
bmp.CreateCompatibleBitmap(pDC, wndrect->Width(), wndrect->Height()); //创建兼容位图,大小与绘图区一致
dcMem.SelectObject(&bmp); //将位图选择进内存DC,显示出来
dcMem.FillSolidRect(wndrect, pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色,这里原本在OnEraseBkgnd调用父类实现的,
//此处实现也就有了原始的背景,然后在背景上作图,复制到DC内存
CBrush cbrush; //新笔刷
CBrush* pBrush; //旧笔刷
cbrush.CreateSolidBrush(RGB(105, 105, 105)); //建立笔刷
pBrush = dcMem.SelectObject(&cbrush); //载入笔刷
dcMem.FillRect(wndrect, &cbrush); //填充底色
dcMem.SelectObject(pBrush); //恢复笔刷
cbrush.DeleteObject();
pBrush->DeleteObject();
dcMem.SetTextColor(RGB(255, 255, 255));
dcMem.SetBkMode(TRANSPARENT);
dcMem.TextOut(0, 0, this->m_strID);
//如果有图像数据就默认显示第一张图像数据
if (this->m_Img.m_ImageContainer.size())
{
//CImage2DC::Show2DC(this->m_Img, dc.GetSafeHdc(), wndrect->Height(), wndrect->Width());
this->m_Img.ShowImage(dcMem.GetSafeHdc(), *wndrect, this->m_Img.m_CurrentPos);
//this->m_Img.DrawPatientInfo(TRUE);
this->m_Img.DrawScalePlate(TRUE);
}
pDC->BitBlt(0, 0, wndrect->Width(), wndrect->Height(), &dcMem, 0, 0, SRCCOPY);//将内存DC上的图象拷贝到前台
dcMem.DeleteDC(); //删除DC
bmp.DeleteObject(); //删除位图
ReleaseDC(pDC);
delete wndrect;
wndrect = nullptr;
运用双缓存技术之后,图像的闪烁有了明显改观:
本文介绍了MFC中双缓存技术的实现,以解决视图窗口在进行复杂绘图操作时产生的闪烁问题。通过将绘图操作先在内存缓冲区完成,然后一次性复制到屏幕,显著减少了闪烁现象。
443

被折叠的 条评论
为什么被折叠?



