一、通過對窗體和控制項使用雙緩衝來減少圖形閃爍(當繪製時出現閃爍時,使用雙緩衝)
對於大多數應用程式,.net framework 提供的預設雙緩衝將提供最佳效果。預設情況下,標準 windows 窗體控制項是雙緩衝的。可以通過兩種方法對窗體和所創作的控制項啟用預設雙緩衝。一種方法是將 doublebuffered 屬性設定為 true,另一種方法是通過呼叫 setstyle 方法將 optimizeddoublebuffer 標誌設定為 true。兩種方法都將為窗體或控制項啟用預設雙緩衝並提供無閃爍的圖形呈現。建議僅對已為其編寫所有呈現**的自定義控制項呼叫 setstyle 方法。
在建構函式裡加上以下**:
1
this
.doublebuffered =
true
;//設定本窗體
2setstyle
(controlstyles.userpaint,
true);
3setstyle
(controlstyles.allpaintinginwmpaint,
true);
// 禁止擦除背景.
4setstyle
(controlstyles.doublebuffer,
true);
// 雙緩衝
5//setstyle(controlstyles.doublebuffer | controlstyles.optimizeddoublebuffer | controlstyles.allpaintinginwmpaint, true);67
//updatestyles();
二、c#控制項的閃爍問題解決方法總結
最近對**作了一些優化,試驗後效果還可以,但是發現介面會閃爍,具體是treeview控制項會閃爍,語言為c#,ide為vs2005。在查閱一些資料,使用了一些基本技術後(如開啟雙緩衝),發現沒什麼效果。
於是使用profiler工具,查詢出瓶頸在於每次更新完介面的endupdate操作(使用這個是為了減少介面更新次數,但這裡不理想是因為控制項中中的元素很多),猜想大概每次更新,.net底層都會更新重繪每個圖元,所以速度會慢,造成閃爍。但是如果這樣,使用雙緩衝應該會有較好效果。再看**,發現可能是更新動作太過頻繁,於是降低速度,有所好轉,但還是不行。
繼續在網上查閱,最終找到乙個方案比較合適。原來底層重繪每次會清除畫布,然後再全部重新繪製,這才是導致閃爍最主要的原因。於是過載訊息傳送函式操作,禁掉這條訊息。**如下:
1
protected
override
void
wndproc
(ref
message m)
2
成功!
注:雙緩衝還是有用的,在更新不是很頻繁且控制項內含元素不是特別多的時候。一旦元素過多,每次更新時間都比較長,即便使用了雙緩衝,仍解決不了閃爍問題。個人認為最終比較理想的方法還是禁掉清除背景訊息。
附:一些嘗試過但失敗的記錄
1)使用setstyle
網上有說使用setstyle函式去設定該控制項的引數,具體為:
setstyle(controlstyles.userpaint | controlstyles.allpaintinginwmpaint | controlstyles.optimizeddoublebuffer, true);
這三個選項引數後者是依賴前者的,必須並存,否則無效。並且這個函式本身是protected的,所以首先需要繼承某控制項再使用。
這個目標是跟前面正確解決方案一致,也是禁止清除背景並開啟雙緩衝,但需要使用使用者繪製選項,而且是全部交由使用者繪製。這需要自己實現控制項的全部繪製,比較麻煩。所以這個方法不是完全不可行,但是需要額外工作量,不推薦。我也沒有使用。
3)使用controlstyles.enablenotifymessage選項
這個選項的作用和正確解決方案也是一致的。使用方法是:
setstyle(controlstyles.enablenotifymessage, true);
protected override void onnotifymessage(message m)
但是實際實驗顯示無效果,不知是什麼原因,沒有細究。
三、個人在乙個winfrom中測試利用timer控制項對要重新整理的控制項進行定時重新整理,可能也能起到作用。
四、c# winform 區域性重新整理
做winform介面程式時,經常會遇到後台處理占用大量時間的情況,這就會造成介面假死狀態。一般解決介面假死有兩種方式:要麼把占用大量時間的處理方式放入其他執行緒;要麼把介面顯示放入其他執行緒。第一種方式應該比較簡單,開單獨的執行緒,處理資料,將處理資料顯示到介面就好。但是我們經常需要在主程式運算一些內容,否則可能會改動比較大。因此,這裡講講第二種方式。
同樣是使用多執行緒,但是c#在其他執行緒重新整理有一點點問題,即不能跨執行緒操作介面。這可以使用控制項的invoke方法解決:
1
private
delegate
void
crossthread()
;2control control =..
..;3
crossthread cross =
delegate()
4;7 control.
invoke
(cross)
;
這樣可以讓控制項在其它執行緒重新整理介面。
再加上開新執行緒後的通用方法:
1
private
void
invaliatecontrol
(control control)2;
10 control.
invoke
(cross);11
}12))
;13}
這樣就可以在任何時候,呼叫此方法對控制項進行重新整理,而不將整個介面重新整理。如果對於同乙個控制項,連續多次重新整理,可以新增乙個成員變數作為標記,以免同一控制項連續多次重新整理,提公升部分效能。
補充:在主線程呼叫耗時操作用此方法可能會有問題,經過驗證呼叫invoke函式,其實是在主線程重新整理介面。
原文出自
C Winform頻繁重新整理導致介面閃爍解決方法
一 通過對窗體和控制項使用雙緩衝來減少圖形閃爍 當繪製時出現閃爍時,使用雙緩衝 對於大多數應用程式,net framework 提供的預設雙緩衝將提供最佳效果。預設情況下,標準 windows 窗體控制項是雙緩衝的。可以通過兩種方法對窗體和所創作的控制項啟用預設雙緩衝。一種方法是將 doublebu...
C Winform頻繁重新整理導致介面閃爍解決方法
收藏 一 通過對窗體和控制項使用雙緩衝來減少圖形閃爍 當繪製時出現閃爍時,使用雙緩衝 對於大多數應用程式,net framework 提供的預設雙緩衝將提供最佳效果。預設情況下,標準 windows 窗體控制項是雙緩衝的。可以通過兩種方法對窗體和所創作的控制項啟用預設雙緩衝。一種方法是將 doubl...
C Winform頻繁重新整理導致介面閃爍解決方法
收藏 一 通過對窗體和控制項使用雙緩衝來減少圖形閃爍 當繪製時出現閃爍時,使用雙緩衝 對於大多數應用程式,net framework 提供的預設雙緩衝將提供最佳效果。預設情況下,標準 windows 窗體控制項是雙緩衝的。可以通過兩種方法對窗體和所創作的控制項啟用預設雙緩衝。一種方法是將 doubl...