「这是我参与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++开发程序猿~