1. 程式人生 > >VS介面繪製雙快取

VS介面繪製雙快取

閃屏的問題

在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();
}