Invalidate(TRUE)的閃屏問題

2021-06-23 04:25:39 字數 1301 閱讀 2111

在使用invalidate(true)進行視窗重繪時,總是會遇到閃屏的問題。

一開始以為是繪圖速度過慢照成的,但在對繪圖時間做了乙個測試之後發現,即使整個繪圖過程只持續了幾個毫秒,還是會看見很明顯的閃爍,所以時間並不是造成閃爍的決定性因素

那到底是什麼原因呢?現在來看看invalidate(true)都幹了些什麼。其實,它只是間接向訊息佇列新增了wm_erasebkgnd和wm_paint兩個訊息。但是,如果使用invalidate(false)的話,則只有wm_paint訊息產生,這時是不會有任何閃爍的。

現在看來,閃爍似乎是由wm_erasebkgnd訊息產生的,事實上,的確與它有關。那wm_erasebkgnd有幹了什麼呢?wm_erasebkgnd訊息由onerasebkgnd()訊息處理函式響應,它的作用就是重繪客戶區背景。我們可以通過向工程裡新增wm_erasebkgnd這個訊息,然後在重寫的訊息處理函式中將返回語句修改為return true來遮蔽這一功能,這樣做的好處是這時不會重繪背景了,壞處是這時背景也不會被擦出來。

好像還沒有說到真實原因,其實真正的原因就隱含在其中。現在來做乙個實驗,分別嘗試一下快速的眨眼和慢速的眨眼,你會發現快速眨眼時我們會感覺眼前的黑色一閃而過,而慢速眨眼時,則會覺得整個過程是連續的,沒有什麼異樣。其實閃爍也就是這麼回事,即多張

不連續影象的快速切換。這裡有三個條件,多張和快速和不連續,而且需要同時具備才會發生閃爍。如果只是兩張,只會感覺到突變,還談不上閃爍;如果頻率慢的話,也相當於兩張影象的情況了;最後如果是連續影象的話,那就像是看電影,平穩的過渡也不會讓人覺得不適。

知道了這些,接下來就可以做決策了。

解決方案

使用invalidate(false),新增wm_erasebkgnd訊息處理函式或者區域性重新整理三者選其一,都是可以解決問題的。它們的都是通過除去影象不連續這一因素來達到目的的。

另外,要說的是gdi的bitblt()函式是及其高效的,一次操作所需要的時間只有幾到十幾個微秒,所以我們可以放心的使用它,而不用擔心任何效率問題。不過相對於bitblt()來說stretchblt()就要慢的多,大概是幾十倍的差別。

還有就是一般的繪圖工作都是先繪製在乙個緩衝區上,然後再一次拷貝到螢幕上。

有時,當我們需要利用閃爍的效果的話,也是可以通過多張影象的快速切換來做到,在這裡我們也將兩張影象的重複切換理解為多張影象。

container of 的的的原理

另外一篇,同樣精彩,揭開linux核心中container of的神秘面紗 華清遠見嵌入式學院講師。在linux 核心中有乙個大名鼎鼎的巨集container of 這個巨集是用來幹嘛的呢?我們先來看看它在核心中是怎樣定義的。呵呵,乍一看不知道是什麼東東。我們先來分析一下container of p...

存在的就是合理的,發生的即是必然的。

筆者有時候會想,什麼是對,什麼是錯?對於追求某一件事情之前首先會考慮,為什麼我要做這件事情。所以經過自我分析和生活周邊環境的總結。我認為,對於乙個人來,這是在站在個體的角度上說。什麼是對的?就是你自己覺得是對的,它就是對的。不過這個只是你自己的想法。主觀上的正確,不代表客觀上也受到了別人的認可。就拿...

Apache的rewrite的重寫相關的引數

apache mod rewrite規則重寫的標誌一覽 使用mod rewrite時常用的伺服器變數 rewriterule規則表示式的說明 匹配任何單字元 chars 匹配字串 chars chars 不匹配字串 chars text1 text2 可選擇的字串 text1或text2 匹配0到1...