MFC雙緩衝實現閃爍的處理

2021-05-27 16:47:39 字數 2342 閱讀 8785

1、顯示的圖形為什麼會閃爍

我們的繪圖過程大多放在ondraw或者onpaint函式中,ondraw在進行螢幕顯示時是由onpaint進行呼叫的。當視窗由於任何原因需要重繪時,總是先用背景色將顯示區清除,然後才呼叫onpaint,而背景色往往與繪圖內容反差很大,這樣在短時間內背景色與顯示圖形的交替出現,使得顯示視窗看起來在閃。如果將背景刷設定成null,這樣無論怎樣重繪圖形都不會閃了。當然,這樣做會使得視窗的顯示亂成一團,因為重繪時沒有背景色對原來繪製的圖形進行清除,而又疊加上了新的圖形。有的人會說,閃爍是因為繪圖的速度太慢或者顯示的圖形太複雜造成的,其實這樣說並不對,繪圖的顯示速度對閃爍的影響不是根本性的。例如在ondraw(cdc *pdc)中這樣寫:

pdc->moveto(0,0);

pdc->lineto(100,100);

這個繪圖過程應該是非常簡單、非常快了吧,但是拉動視窗變化時還是會看見閃爍。其實從道理上講,畫圖的過程越複雜越慢閃爍應該越少,因為繪圖用的時間與用背景清除螢幕所花的時間的比例越大人對閃爍的感覺會越不明顯。比如:清楚螢幕時間為1s繪圖時間也是為1s,這樣在10s內的連續重畫中就要閃爍5次;如果清楚螢幕時間為1s不變,而繪圖時間為9s,這樣10s內的連續重畫只會閃爍一次。這個也可以試驗,在ondraw(cdc *pdc)中這樣寫:

for(int i=0;i<100000;i++)

程式有點極端,但是能說明問題。

說到這裡可能又有人要說了,為什麼乙個簡單圖形看起來沒有複雜圖形那麼閃呢?這是因為複雜圖形佔的面積大,重畫時造成的反差比較大,所以感覺上要閃得厲害一些,但是閃爍頻率要低。那為什麼動畫的重畫頻率高,而看起來卻不閃?這裡,我就要再次強調了,閃爍是什麼?閃爍就是反差,反差越大,閃爍越厲害。因為動畫的連續兩個幀之間的差異很小所以看起來不閃。如果不信,可以在動畫的每一幀中間加一張純白的幀,不閃才怪呢。

2、解決辦法:

在圖形圖象處理程式設計過程中,雙緩衝是一種基本的技術。我們知道,如果窗體在響應wm_paint訊息的時候要進行複雜的圖形處理,那麼窗體在重繪時由於過頻的重新整理而引起閃爍現象。解決這一問題的有效方法就是雙緩衝技術。

因為窗體在重新整理時,總要有乙個擦除原來圖象的過程onerasebkgnd,它利用背景色填充窗體繪圖區,然後在呼叫新的繪圖**進行重繪,這樣一擦一寫造成了圖象顏色的反差。當wm_paint的響應很頻繁的時候,這種反差也就越發明顯。於是我們就看到了閃爍現象。

我們會很自然的想到,避免背景色的填充是最直接的辦法。但是那樣的話,窗體上會變的一團糟。因為每次繪製圖象的時候都沒有將原來的圖象清除,造成了圖象的殘留,於是窗體重繪時,畫面往往會變的亂七八糟。所以單純的禁止背景重繪是不夠的。我們還要進行重新繪圖,但要求速度很快,於是我們想到了使用bitblt函式。它可以支援圖形塊的複製,速度很快。我們可以先在記憶體中作圖,然後用此函式將做好的圖複製到前台,同時禁止背景重新整理,這樣就消除了閃爍。以上也就是雙緩衝繪圖的基本的思路。

3、具體步驟:

假設我們建立了乙個draw的工程,我們要在drawview中進行繪圖操作。

在雙緩衝方法中,首先要做的是遮蔽背景重新整理。背景重新整理其實是在響應wm_erasebkgnd訊息。我們在視類(cdrawview)中新增對這個訊息的響應,可以看到預設的**如下:

bool cdrawview::onerasebkgnd(cdc* pdc)

接下來是雙緩衝的實現步驟:

(1)增加成員變數(在drawview.h檔案中)

//引數宣告

cbitmap* m_poldbitmap;

cbitmap* m_pmembitmap; //宣告記憶體中承載臨時圖象的點陣圖

cdc* m_pmemdc;   //宣告用於緩衝作圖的記憶體dc

(2)初始化變數(在drawview的建構函式中)

m_pmemdc=new cdc();

m_pmembitmap=new cbitmap();

(3)增加訊息響應函式

wm_create(在drawview.cpp中)

int cdrawview::oncreate(lpcreatestruct lpcreatestruct)

(4)修改ondraw()函式(drawview.cpp中)

void cdrawview::ondraw(cdc* pdc)

(5)自己的繪圖函式(drawview.cpp中)

void drawsomething()

(6)delete掉new的東西(在drawview的析構函式中)

delete m_pbitmap;

delete m_pmemdc;

作者說明:

步驟有點多,一時可能不好明白,建議仔細的看,應該會看明白了,如果有什麼建議或者有錯誤的地方請網友指正,感謝以下網友的資料,在此列出,朋友們也可去下面的位址看看,本文是綜合以下文章後得到的。

參考資料:

來自

mfc下實現雙緩衝的方法

本帖解決的問題 如何實現雙緩衝 為什麼實現了雙緩衝還是會閃爍?以下資料為本人積累和加上自己的經驗 1 簡介一下windows mfc的view顯示重新整理過程 1 使用背景刷填充view窗體 呼叫內在機制的 2 呼叫onpain ondraw 呼叫使用者的 2 產生閃爍的原因出在於 當我們很快地重新...

MFC 雙緩衝技術

在做俄羅斯方塊遊戲的時候,遇到遊戲過程中螢幕閃爍問題,解決辦法如下 使用雙緩衝技術解決螢幕閃爍 修改檢視類的ondraw 函式 void cmytetrisview ondraw cdc pdc 修改檢視類的drawimage 函式 cmytetrisview 訊息處理程式 void cmytetr...

mfc雙緩衝技術

mfc繪圖時,頻繁的重新整理會導致螢幕閃爍現象,採用雙緩衝技術可以解決閃爍問題。主要方法是將影象先存在記憶體中,然後一次性顯示在螢幕上 步驟 去掉背景重新整理 bool c上位機view onerasebkgnd cdc pdc 在view類中修改ondraw函式 crect rect getcli...