グラフィックを表示するアプリケーションでは、ウィンドウをリサイズしたときなどにその表示がちらつくことがある。例えば、「TIPS:ウィンドウのリサイズ時に再描画を行うには?」で示したサンプル・プログラムがその一例である。本稿では再描画時のちらつきをなくすための方法について解説する。
OnPaintBackgroundメソッドの無効化
描画がちらつく原因は、OnPaintメソッド(あるいはPaintイベントのイベント・ハンドラ)で実際の描画を行う前に、背景が自動的に消去されるためだ。背景の消去とは、具体的には、Formクラス(System.Windows.Forms名前空間)のBackgroundImageプロパティで指定されている画像の描画や、BackColorプロパティで指定されている色による塗りつぶしのことである。
特にクライアント領域全体にグラフィックを描画するようなアプリケーションでは、プログラムですべての描画を行うため、このような背景の消去はまったく不要である。
背景の消去(描画)は、Formクラスのスーパー・クラスであるControlクラス(System.Windows.Forms名前空間)のOnPaintBackgroundメソッドで行われている。よって、再描画時のちらつきをなくすためにはOnPaintBackgroundメソッドを空のメソッドでオーバーライドすればよい。
次のサンプル・コード*は、「TIPS:ウィンドウのリサイズ時に再描画を行うには?」で示したサンプル・プログラムに、空のOnPaintBackgroundメソッドを追加したものだ。
* このサンプル・コードを試すには、まずVisual Studio .NETで新しいプロジェクトとして「Windows アプリケーション」を選択してプロジェクトを作成する。そしてフォームをダブルクリックしてコードを開き、自動作成されているForm1_Loadメソッドを削除してから、このサンプル・コードをコピー&ペーストすればよい。
Image bitmap;
private void Form1_Load(object sender, System.EventArgs e)
{
System.Net.WebClient wc = new System.Net.WebClient();
System.IO.Stream stream = wc.OpenRead("http://www.atmarkit.co.jp/fdotnet/images/fdotnet_m.gif");
bitmap = new Bitmap(stream);
stream.Close();
this.ClientSize = bitmap.Size;
this.SetStyle(ControlStyles.ResizeRedraw, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(bitmap, this.ClientRectangle);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// 何もしない
// base.OnPaintBackground(pevent);
}
Dim bitmap As Image
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Dim wc As System.Net.WebClient = New System.Net.WebClient
Dim stream As System.IO.Stream = wc.OpenRead("http://www.atmarkit.co.jp/fdotnet/images/fdotnet_m.gif")
bitmap = New Bitmap(stream)
stream.Close()
Me.ClientSize = bitmap.Size
Me.SetStyle(ControlStyles.ResizeRedraw, True)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.DrawImage(bitmap, Me.ClientRectangle)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
' 何もしない
End Sub
ControlStyles.Opaqueの設定
あるいは、次のようにしてフォームのコントロール・スタイルに「ControlStyles.Opaque」を設定しておいても同様の効果が得られる(デフォルトではこの設定はfalseとなっている)。
this.SetStyle(ControlStyles.Opaque, true);
コントロール・スタイルのControlStyles.Opaqueは、描画時に無効領域の背景を消去する(falseに設定時)か、そのままにするか(trueに設定時)を決定するフラグである。これをtrueにした場合には背景は消去されず(描画されず)、OnPaintBackgroundメソッドの呼び出しもスキップされる。
次のサンプル・コードは、先のサンプル・コードをControlStyles.Opaqueの設定を使用して書き換えたものだ。
Image bitmap;
private void Form1_Load(object sender, System.EventArgs e)
{
System.Net.WebClient wc = new System.Net.WebClient();
System.IO.Stream stream = wc.OpenRead("http://www.atmarkit.co.jp/fdotnet/images/fdotnet_m.gif");
bitmap = new Bitmap(stream);
stream.Close();
this.ClientSize = bitmap.Size;
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Opaque, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(bitmap, this.ClientRectangle);
}
// protected override void OnPaintBackground(PaintEventArgs pevent)
// {
// // 何もしない
// // base.OnPaintBackground(pevent);
// }
このコードを含むフォーム(Form1.cs)のダウンロード
Dim bitmap As Image
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Dim wc As System.Net.WebClient = New System.Net.WebClient
Dim stream As System.IO.Stream = wc.OpenRead("http://www.atmarkit.co.jp/fdotnet/images/fdotnet_m.gif")
bitmap = New Bitmap(stream)
stream.Close()
Me.ClientSize = bitmap.Size
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Me.SetStyle(ControlStyles.Opaque, True)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.DrawImage(bitmap, Me.ClientRectangle)
End Sub
' Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
' ' 何もしない
' End Sub
このコードを含むフォーム(Form1.vb)のダウンロード
基本的に、ここで示した方法はクライアント領域全体に描画するようなアプリケーションに適用できるものだ。クライアント領域の一部にのみ描画するようなアプリケーションでは、当然ながら、その領域以外の部分が描画されずにゴミが残ることになる。
なお、背景の消去によるちらつきを防止しても、描画するグラフィックが複雑である場合には、描画によるちらつきが発生することがある。これを抑えるために「ダブル・バッファリング」という機能がフォームには用意されているが、これについては「TIPS:ダブル・バッファリングにより描画を行うには?」で解説している。
カテゴリ:Windowsフォーム 処理対象:ウィンドウ
使用ライブラリ:Controlクラス(System.Windows.Forms名前空間)
使用ライブラリ:Formクラス(System.Windows.Forms名前空間)
使用ライブラリ:ControlStyles列挙体(System.Windows.Forms名前空間)
関連TIPS:ウィンドウのリサイズ時に再描画を行うには?
関連TIPS:ダブル・バッファリングにより描画を行うには?
Copyright© Digital Advantage Corp. All Rights Reserved.