C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 25 を表示中)
■11413 / )  Re[8]: ListViewのちらつき、仮想化について
□投稿者/ れい (301回)-(2007/12/13(Thu) 13:00:28)
ちらつきをまとめてみました。
やはり私はうそつきでした。今度からうそつきと呼んでください。

しかも前に同じこと調べてました。記憶が混乱してたみたい。
一体何回調べれば覚えるんだろう…。

------------------------------------------------

■言葉の定義
・ちらつき=フリッカ=flicker=上書きされて消えるべきものが一瞬見えてしまう状態
・ズレ=テアリング=tearing=フレーム更新中に画像が更新され、ズレてしまう状態

■一般的回避策

・フリッカの回避策
上書きを行わないor実際に表示される前に上書きを終える。
普通はダブルバッファを行う。
メモリ転送が遅ければ、テアリングを助長することもありうる。

・テアリングの回避策
フレーム更新とオンスクリーンバッファの更新が重ならないようにする。
普通は同期して更新する。
ローレベルなサポートがないと対策は困難。
DWMで改善。

■Windows/.Net Windows.Forms におけるフリッカ対策

○あきらめる

○Win32のWS_EX_COMPOSITED

XP以降で用いることができる。

CreateParamsを継承して設定する。

WS_EX_COMPOSITEDを指定したウィンドウおよびその子ウィンドウの描画を
オフスクリーンバッファで行い、WM_PAINT終了後に更新するという処理をOSがやってくれる。

CS_CLASSDC、CS_OWNDCを持つウィンドウには適用されない。

その他ScrollBarに対してはうまく効かなかったり、TabControlでごみが残ったり、
トップレベルウィンドウに効かなかったり、
激しくバグあり且つバージョン依存が激しい。

DWMでは問題は減っている。

○.NetのDoubleBuffered / ControlStyles.OptimizedDoubleBuffer

ウィンドウのOnPaint、OnPaintBackgroundをBufferedGraphics対象に行い、
WM_PAINT終了時にBufferedGraphics.Renderすることで
ちらつきを防ぐ。

継承してコンストラクタでDoubleBuffered=trueとしたり、
DoubleBufferedをオーバーライドしてreturn trueとしたり、
SetStyleしたりして設定する。

描画にはBufferedGraphicsが用いられる。

ウィンドウ単位でのダブルバッファになるので、子ウィンドウがあるとダメ。

OSによって描画されるコントロール(TextBoxやStatusBar、DateTimePickerなど)は効かない。

ListViewは例外。DoubleBufferedをtrueにするとLVS_EX_DOUBLEBUFFERが適用され、
それによってダブルバッファされる。

○その他の方法

TreeViewはVista以降ならTVS_EX_DOUBLEBUFFER(0x02000000)を指定すればダブルバッファされる。

コントロールがたくさんあってちらつく場合はコントロールをWS_EX_COMPOSITEDなPanelに入れるとよい。

Tabコントロールの場合はTabControlにWS_EX_COMPOSITEDを指定するのではなく、
TabPageにWS_EX_COMPOSITEDを指定するとゴミが出にくい。

■その他。

・ダブルバッファはメモリを大量に食うので注意。
・うそ情報の可能性が高いので鵜呑みにしない。

返信 編集キー/


管理者用

- Child Tree -