【MFC】使用CMemDC解决图像显示闪烁问题

图像闪烁原因分析

闪烁的原因是在快速频繁的 调整图像的显示内容时,总是要有一个操作便是刷新背景再填充图像,快速切换图像过程中背景与图像的强烈反差导致了闪烁的问题。

闪烁解决方案

  1. 不刷背景

    不刷新背景,只刷新前景图片可以有效的解决图像闪烁问题,但是随之而来的如果图像没有完整的覆盖目标区域,未覆盖区域将无法更新去除下层显示的数据,如果不涉及为完全覆盖问题 避免刷新背景是最佳的实现方案 

    手动通知刷新时InvalidateRect(CRect(0,0,cx,cy), 0); 第一个参数是刷新范围,第二个参数写0便可以避免更新背景。

  2. 避免直接在显示屏DC刷背景

其实闪烁的最直接原因就是DC绘制到屏幕上的速度太慢,而且还分背景和前景 分别绘制两次 这导致了存在大量时间的窗口空白期,因此无论你电脑性能多高,多次刷新屏幕显示总能看到闪烁,那么知道时间消耗的地方后,便有另一种方式去减少时间的消消耗和时间的占用,便是减少直接向显示屏的绘制次数 和修改时间。

使用新增DC管理类CMemDC,对屏幕OnDraw(CDC* pDC)的pDC指针进行管理,使用后 绘制操作没有变换,并且其创建一个等大的内存DC作为缓存区,在CMemDC析构的时候把缓存数据一次性的写入到屏幕显示区中。

代码演示如下:
代码说明,因为CMemDC 在”析构的时候才把缓存区数据写入屏幕“这一特性,CMemDC不能长期存在于成员变量,具体其他实现方案自行开发,这里仅作演示。

我先获取客户区大小,在内存中填充背景颜色(FillRect),再在内存中绘制目标图像m_CDC,这几个操作均在内存中消耗时间仅在10ms以内, 此函数退出后,调用CMemDC的析构函数,图像一次性绘制到显示区域

提示,OnDraw中不宜做过多运算,虽然先写入内存DC能极大的提高速度,但是如果此处的运算量过多仍然出现显示卡顿的问题,所以这里建议,尽可能的分开运算。

有人建议直接关闭背景的绘制操作,我这里建议不要这么做

void CMFCView::OnDraw(CDC* pDC)
{
	CMFCDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	CMemDC memDC(*pDC,this);
	pDC = &memDC.GetDC();

	// TODO: 在此处为本机数据添加绘制代码
	CRect rect;
	GetClientRect(&rect);
	COLORREF  colorVal = RGB(50, 50, 50);
	//pDC->FloodFill(0,0,colorVal);
	pDC->FillRect(rect,&CBrush(colorVal));
	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_CDC, 0, 0, SRCCOPY);
}

关于CMemDC 类定义 

在VS内置库 Path:..\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\atlmfc\include\afxcontrolbarutil.h

class CMemDC
{
public:
	AFX_IMPORT_DATA static BOOL m_bUseMemoryDC;

	CMemDC(CDC& dc, CWnd* pWnd);
	CMemDC(CDC& dc, const CRect& rect);

	virtual ~CMemDC();

	CDC& GetDC() { return m_bMemDC ? m_dcMem : m_dc; }
	BOOL IsMemDC() const { return m_bMemDC; }
	BOOL IsVistaDC() const { return m_hBufferedPaint != NULL; }

protected:
	CDC&     m_dc;
	BOOL     m_bMemDC;
	HANDLE   m_hBufferedPaint;
	CDC      m_dcMem;
	CBitmap  m_bmp;
	CBitmap* m_pOldBmp;
	CRect    m_rect;
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值