.NET TIPS

PictureBoxコントロールにグラフィックを描画するには?

デジタルアドバンテージ 遠藤 孝信
2006/06/09

 Windowsフォーム用のPictureBoxコントロールは基本的に画像ファイルやWeb上の画像を表示するためのものだが、プログラムからグラフィックを描画するためにPictureBoxコントロールを使いたいというニーズは多い。本稿ではPictureBoxコントロール(以下、単にPictureBox)へ描画する方法についてまとめる。

任意のタイミングで直接描画

 例えば、ボタンがクリックされたときにPictureBoxにグラフィックを描画するには、次のようにCreateGraphicsメソッドによりGraphicsオブジェクト(System.Drawing名前空間)を取得し、それに対して描画を行えばよい(以降ではmyPaintingメソッドが実際の描画を行うものとする)。

// ボタンのClickイベント・ハンドラ
private void button1_Click(object sender, EventArgs e) {
  Graphics g = pictureBox1.CreateGraphics();
  myPainting(g);
}
' ボタンのClickイベント・ハンドラ
Private Sub Button1_Click(ByVal sender As Object, ByVal e AsEventArgs) Handles Button1.Click
  Dim g As Graphics = PictureBox1.CreateGraphics()
  myPainting(g)
End Sub
ボタンがクリックされたときにPictureBoxに描画するコード(上:C#、下:VB)
C#版ではpictureBox1、VB版ではPictureBox1がPictureBoxコントロールのインスタンスとする。また、myPaintingメソッドが実際にグラフィックの描画を行うものとする。

 ただしこのようにして描画した内容は、ウィンドウをリサイズしたとき(ウィンドウをいったん小さくしてから元のサイズに戻した場合など)や、PictureBoxを覆っていた別のウィンドウが移動したときなどに消えてしまう(リサイズやほかのウィンドウなどにより無効になった画面領域はプログラム自身で再描画する必要があるため)。

Paintイベントで描画

 描画したグラフィックの内容が消されずに常に表示されるようにするには、Paintイベントが発生したタイミングでグラフィックを描画しなければならない。これは、グラフィックの描画に必要なデータ(例えばラインならその始点と終点の座標など)をすべて保持しておき、Paintイベント・ハンドラですべてのグラフィックを再描画できるように常に準備しておく必要があることを意味する。

 Paintイベント・ハンドラとなるメソッドでは、メソッドの第2パラメータのGraphicsプロパティからGraphicsオブジェクトを取得できるようになっているため、次のようにしてPictureBoxにグラフィックを描画できる。

// PictureBoxのPaintイベント・ハンドラ
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
  myPainting(e.Graphics);
}
' PictureBoxのPaintイベント・ハンドラ
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles PictureBox1.Paint
  myPainting(e.Graphics)
End Sub
PaintイベントでPictureBoxに描画するコード(上:C#、下:VB)
Paintイベントは再描画が必要な場合に発生する。

 以上の2つの描画方法は、実際にはPictureBoxに限ったものではなく、フォームも含め基本的にすべてのコントロールで可能だ。いうなれば、これらの方法は単にコントロールの表面にグラフィックを上書きしているようなものだ。

 また、描画されたグラフィックの保存は、.NET Framework 2.0では「TIPS:フォームやコントロールの画像をファイルに保存するには?」で示した方法により可能だが、.NET Framework 1.xでは容易でない。

Imageプロパティで指定したビットマップに描画

 PictureBoxにグラフィックを描画する場合のより合理的な方法は、あらかじめPictureBoxと同じサイズのBitmapオブジェクト(System.Drawing名前空間)を作成してPictureBoxのImageプロパティに設定しておき、グラフィックの描画はそのBitmapオブジェクトに対して行うというやり方だ。

 次のサンプル・コードでは、フォームのコンストラクタでBitmapオブジェクトを作成し、ボタンがクリックされたときにグラフィックの描画を行う。

// フォームのコンストラクタ
public Form1() {
  InitializeComponent();

  // PictureBoxと同サイズのBitmapオブジェクトを作成
  Bitmap bmp =
    new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height);
  pictureBox1.Image = bmp;
}

// ボタンのClickイベント・ハンドラ
private void button1_Click(object sender, EventArgs e) {
  Graphics g = Graphics.FromImage(pictureBox1.Image);
  myPainting(g); // Bitmapオブジェクトに描画
  pictureBox1.Refresh(); // PictureBoxを更新(再描画させる)
}
' フォームのコンストラクタ
Sub New()
  ' この呼び出しは、Windows フォーム デザイナで必要です。
  InitializeComponent()

  ' PictureBoxと同サイズのBitmapオブジェクトを作成
  Dim bmp As New _
    Bitmap(PictureBox1.Size.Width, PictureBox1.Size.Height)
  PictureBox1.Image = bmp
End Sub

' ボタンのClickイベント・ハンドラ
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
  Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
  myPainting(g) ' Bitmapオブジェクトに描画
  PictureBox1.Refresh() ' PictureBoxを更新(再描画させる)
End Sub
PaintイベントでPictureBoxに描画するコード(上:C#、下:VB)
Paintイベントはコントロールの再描画が必要な場合に発生する。

 この方法では、PictureBox自身がPaintイベント発生時にImageプロパティに設定されているBitmapオブジェクトを再描画するため、プログラムで明示的にPaintイベントを処理する必要はない。

 またこのようにして描画を行っておけば、その画像をファイルに保存したい場合にも、BitmapオブジェクトのSaveメソッドを使用するだけでよい(参照「TIPS:画像をファイルに保存するには?」)。

 ただしBitmapオブジェクトに対して描画したものをすぐにPictureBoxに反映するためには、PictureBoxのRefreshメソッドを呼び出して、PictureBoxを強制的に更新しなければならない(RefreshメソッドはPictureBoxの画像領域を無効にし、Paintイベントを発生させる)。End of Article

カテゴリ:Windowsフォーム 処理対象:コントロール
使用ライブラリ:PictureBoxコントロール(System.Windows.Forms名前空間)
使用ライブラリ:Graphicsクラス(System.Drawing名前空間)
使用ライブラリ:Bitmapクラス(System.Drawing名前空間)
関連TIPS:フォームやコントロールの画像をファイルに保存するには?
関連TIPS:画像をファイルに保存するには?

この記事と関連性の高い別の.NET TIPS
ダブル・バッファリングにより描画を行うには?(DoubleBuffered編)
ダブル・バッファリングにより描画を行うには?
スクロールバー付きでPictureBoxコントロールに画像に表示するには?
背景の描画を禁止して再描画時のちらつきをなくすには?
Windowsフォームで簡単に画像を表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH