2011/03/23

[C#]Graphics再描画時のちらつき対処

このエントリーをはてなブックマークに追加
いわゆるダブルバッファリングというやつです。

ちらつく理由

直にFormのGraphicsに描画すると、何かの拍子にFormの再描画が必要になったとき(背面にもぐって前面に表示されるようなとき)に、表示されていた描画内容が消えてしまいます。再描画の要求、つまりOnPaintイベントのたびに、イチからせこせこと描画するようなことをすると、どうしても内容がちらついて見えてしまいます。
フォーム画面に描画を行わずに、あらかじめBitmapオブジェクトを準備しておいて、Bitmapオブジェクに描画を行うようにします。そうして、フォーム画面の再描画の要求時には、必要なところだけをBitmapオブジェクトから複製したものを表示させてあげればよいというわけです。描画内容がどんなに複雑になっても、再描画時には一定の範囲をコピーするだけなので、気にしなくてよいという利点があります。

このテクニックを「ダブルバッファリング」と言うのでした。

サンプルコード
public partial class Form1 : Form {
  private Bitmap _bmp = null; // Bitmapオブジェクトの追加

  // コンストラクタ
  public Form1() {
    InitializeComponent();

    // フォーム画面の描画サイズと同じBitmapオブジェクトを作成する
    this._bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
    this.DoubleBuffered = true; // C#2.0以降
  }

  // 再描画の要求時
  protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    // bitmapオブジェクトから必要なところだけを複製する
    e.Graphics.DrawImageUnscaled(this._bmp, 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
  }

  // 描画処理
  private void Draw() {
    Graphics g = Graphics.FromImage(this._bmp);
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

    // 同心円を40個描く
    int cx  =this.ClientRectangle.Width / 2;
    int cy  =this.ClientRectangle.Height / 2;
    for (int i = 0; i < 40; i++) {
      int size = 4 + i * 8;
      g.DrawEllipse(Pens.OrangeRed, cx - size / 2, cy - size / 2, size, size);
    }

    g.Dispose();
    this.Invalidate(); // フォームに再描画を要求させる
  }

  // 描画処理の呼び出しのためにbuttonを一つ置いてください
  private void button1_Click(object sender, EventArgs e) {
      this.Draw();
  }
}
実行結果
上のサンプルコードを実行するとこんな感じになります。

0 件のコメント :

コメントを投稿