MFC|双缓存绘图机制

411 阅读3分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。

最近在用MFC框架做开发,突然间想到了绘制图形刷新不及时的问题,就想来跟大家分享一下。说心里话,使用MFC绘图真的好麻烦呀,尤其是绘制心电图、波形图时,如果只是用普通的绘制就会导致上次的图形未被清除,这次的新图形又画上去了,多次重叠。内容绘制不正确而且看起来很是难看。

有些时候我们在使用OnPaint绘制图形或者是控件重绘时,会发现控件上的贴图会闪烁。这是因为在短时间内频发出现背景色与显示的图片交替出现的情况,那么我们该如何避免这种情况发生呢?

只要去掉MFC提供的背景绘制过程或者是重载OnEraseBkgnd。

那么,在绘图时,我们该如何进行操作呢?

接下来,我们就以控件的自绘来说明,有些控件的自绘是需要双缓存机制的,例如:CHeaderCtrl控件,这是CListCtrl的表头类,这里不详细说明该类是如何绘制的,仅仅说明该类用到了双缓存机制。

CXXDlg::OnPaint中实现双缓存机制

第一步:获取显示的客户端区域大小

CRect rRect;  
GetClientRect(&rRect);  

第二步:定义位图对象

CDC memDC;  
CBitmap memBitmap;

在后续的绘制中,都会将所有的图形绘制在CDC上面

第三步:设置Bitmap画刷填充整个区域

CBrush brush;  
brush.CreateSolidBrush(m_crBackground);

设置当前双缓存的默认背景色

第四步:创建与指定设备兼容的内容设备上下文环境

memDC.CreateCompatibleDC(&dc);

设备上下文环境呗创建后,显示的界面仅仅是一个标准的一个单色像素宽和高

并且,在绘制图形之前一定要通过CDC::CreateCompatibleDC指定环境。

第五步:创建扩展内存设备环境图像空间

说的有点高深,大家就记住了,有第四步的时候一定要有第五步,它们两个是并列出现的。

memBitmap.CreateCompatibleBitmap(&dc, rRect.Width(), rRect.Height());

第六步:将位图信息绑定到CDC上

CBitmap *pOldMemBmp = memDC.SelectObject(&memBitmap); 

在这里,我们需要注意的是,我用了一个pOldMemBmp来存储绑定的返回值,主要是为了在绘图结束之后可以释放绑定的bitmap,否则绘图过多就是导致内存泄漏。

第七步:自定义绘制

到这里,就可以实现绘制功能了,比如绘制图片,绘制文本等等。。。

第八步:BitBlt图形

这也是最重要的一步,将绘制好的内容映射到目标设备上,如果缺少这一步骤,绘制的图形将不会显示出来的。

dc.BitBlt(0,0, rRect.Width(), rRect.Height(), &memDC, 0, 0, SRCCOPY); 

第九步:释放在绘制图形中用到的资源

memDC.SelectObject(pOldMemBmp);
dc.SelectObject(memBitmap);
memDC.SelectObject(OldFont);
DeleteObject(brush);
memBitmap.DeleteObject();
memDC.DeleteDC();

到这里,MFC的双缓存机制就已经绘制完成啦~

我是中国好公民st,一名C++开发程序猿~