連載
» 2004年08月19日 05時00分 公開

.NET TIPS:背景の描画を禁止して再描画時のちらつきをなくすには?

[遠藤孝信,デジタルアドバンテージ]
.NET TIPS
Insider.NET


「.NET TIPS」のインデックス

連載目次

 グラフィックを表示するアプリケーションでは、ウィンドウをリサイズしたときなどにその表示がちらつくことがある。例えば、「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);
}

OnPaintBackgroundメソッドを無効化したC#のサンプル・コード

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

OnPaintBackgroundメソッドを無効化したVB.NETのサンプル・コード

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);
// }

コントロール・スタイルの設定により背景の消去を行わないC#のサンプル・コード
このコードを含むフォーム(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

コントロール・スタイルの設定により背景の消去を行わないVB.NETのサンプル・コード
このコードを含むフォーム(Form1.vb)のダウンロード

 基本的に、ここで示した方法はクライアント領域全体に描画するようなアプリケーションに適用できるものだ。クライアント領域の一部にのみ描画するようなアプリケーションでは、当然ながら、その領域以外の部分が描画されずにゴミが残ることになる。

 なお、背景の消去によるちらつきを防止しても、描画するグラフィックが複雑である場合には、描画によるちらつきが発生することがある。これを抑えるために「ダブル・バッファリング」という機能がフォームには用意されているが、これについては「TIPS:ダブル・バッファリングにより描画を行うには?」で解説している。

カテゴリ:Windowsフォーム 処理対象:ウィンドウ
使用ライブラリ:Controlクラス(System.Windows.Forms名前空間)
使用ライブラリ:Formクラス(System.Windows.Forms名前空間)
使用ライブラリ:ControlStyles列挙体(System.Windows.Forms名前空間)
関連TIPS:ウィンドウのリサイズ時に再描画を行うには?
関連TIPS:ダブル・バッファリングにより描画を行うには?


■更新履歴

【2004/08/19】関連TIPSとして「TIPS:ダブル・バッファリングにより描画を行うには?」についての記述を追加しました。

【2004/08/06】初版公開。


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。