不用雙緩衝實現無閃爍圖象

首先說一下產生閃爍的原因,當窗口由於任何原因需要重繪時,總是先用背景色或背景圖象將顯示區清除,然後才顯示圖象,這樣在短時間內背景色與顯示圖形交替出現,使得顯示窗口看起來在閃。如果將背景刷設置成NULL,這樣無論怎樣重繪圖形都不會閃了,但是會使得窗口的顯示亂成一團,因爲重繪時沒有背景色對原來繪製的圖形進行清除,而又疊加上了新的圖形。

一般的解決方法就是採用雙緩衝,創建一幅內存圖象,把背景和圖片先繪製到該圖象,然後把繪製好的該圖象顯示到窗口,這樣就不會產生閃爍,其實就是隱藏了圖象的顯示過程,原來是在前臺,給你看到先在畫布上刷上背景,再畫上圖象,現在是在後臺畫好了再拿出來給你看。

看起來好象解決方法是需要一次性繪製好圖象,其實關鍵是不能讓任何背景及圖片在繪製時產生重疊,跟是否一次性繪製沒多大關係。電腦的繪製速度還是很快的,不信可以試試把背景刷設置成NULL,這樣不會閃爍,然後循環調用BitBlt把一幅小圖片鋪滿整個窗口,雖然是多次繪製,一樣不會閃爍,但是如果改變一下循環步長,讓圖片產生重疊,就會開始閃爍了。

知道了閃爍的原因,不用雙緩衝的解決辦法就不難找到了,調用ExcludeClipRect,可以排除掉繪製區域,先繪製圖片,ExcludeClipRect掉圖片的區域,再繪製背景,相當於把一幅挖了一個洞的畫布貼到窗口,這樣不產生繪製重疊部分,就不會產生閃爍了。

API代碼,始終在窗口右下角顯示一幅300*200的圖片,窗口背景爲黑色:

case WM_PAINT:
{
 PAINTSTRUCT ps;
 RECT rc;
 HDC hMemDC;
 
 GetClientRect(hWnd,&rc);
 BeginPaint(hWnd,&ps);
 hMemDC = CreateCompatibleDC(ps.hdc);
 SelectObject(hMemDC,hbmp);
 BitBlt(ps.hdc,rc.right-300,rc.bottom-200,300,200,hMemDC,0,0,SRCCOPY);
 ExcludeClipRect(ps.hdc,rc.right-300,rc.bottom-200,rc.right,rc.bottom);
 FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
 DeleteDC(hMemDC);
 EndPaint(m_hWnd,&ps);
 return 0;
}

有時候因爲刷新區域的問題,可能調整窗口但是WM_PAINT的代碼不起作用,這時需要響應WM_SIZE消息,通知畫面更新一下:
case WM_SIZE:
 InvalidateRect(hWnd,NULL,FALSE);
 break;
 

對於顯示多幅圖象,這個方法也是適用的,只要每繪製完一幅圖象,ExcludeClipRect掉該圖象區域就可以,但是注意如果圖象有重疊,繪製順序是反過來的,即蓋在最上面的圖象需要最先繪製,最後給整個窗口刷上背景就OK了。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章