VS绘制效率低引起的屏幕闪烁-解决方法

解决方法:采用双缓冲、用GetClipBox部分重绘

转自:https://blog.csdn.net/bingdianlanxin/article/details/53836195

闪屏的问题

在GDI的绘图系统中,每调用一次区域绘图操作,如FillRect、BitBlt等,图形显示系统就会在屏幕中对指定的区域进行一次刷新操作。如果频繁的进行区域绘制操作的操作的话,我们就会发现,屏幕会出现闪屏。

双缓存
产生闪屏的原因是类似于多进程之间的通信问题,每次DC的绘图操作,都要把相关的显示数据发送到显卡,显卡处理后,在显示器上显示。借鉴提升多线程之间的通信效率的解决方法,可通过减少与显卡之间的交互次数来提升绘制的效率。这也就是双缓存的思路。双缓存的原理是先把更新操作中所有绘制数据先写入内存,然后再调用BitBlt或StretchBlt一次性的把所有数据发送到显卡中。

取消擦除背景
1.取消重绘时的擦除选项。如使用Invalidate(FALSE)。
2.截断擦除消息。背景的擦除是通过WM_ERASEBKGND消息来完成。于是,我们只要截获了该消息,就能彻底取消擦除背景。可在窗口类中为WM_ERASEBKGND提供消息响应函数,然后直接返回TRUE。

绘制效率的提升
在刷新界面的时候,刷新的区域越小,刷新效率更高,因此,在刷新界面的时候,我们应该尽量较少不必要的刷新。操作系统也会对界面的刷新操作进行优化,如拉动滚动条的时候,并不是对整个界面进行刷新,而只是对已经无效的区域中换上新的图形,然后再在屏幕调整图形区域在界面上的位置。因此,就有一个裁剪区域的概念,在重绘的过程中,只有裁剪区域需要重绘。因此,我们在双缓存中,也只需对裁剪区域重绘。可通过CDC::GetClipBox来获得裁剪区域的大小。

void CDlgTest::OnPaint()
{
	CPaintDC dc(this); // device context for painting
 
	CRect rcClient;
	GetClientRect(&rcClient);
 
	//创建内存DC
	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);
 
	//设置内存DC的画板
	CBitmap bmpMem;	
	if (bmpMem.CreateCompatibleBitmap(&dc,rcClient.Width(),rcClient.Height()))
	{
		CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);
		CWnd::DefWindowProc(WM_PAINT,(WPARAM)dcMem.m_hDC,0);
 
		/*功能实现代码。。。。。。*/
 
		//把内存DC复制到输入DC中
		dc.BitBlt(0,0,rcClient.right,rcClient.bottom,&dcMem,0,0,SRCCOPY);
 
		//释放资源
		dcMem.SelectObject(pOldBmp);
		bmpMem.DeleteObject();
	}
	dcMem.DeleteDC();
}

猜你喜欢

转载自blog.csdn.net/qq_16334327/article/details/81106650