C#のPictureBoxでImageをセットしない状態で図形を描画

C# コンピュータ
C#

PictureBoxを使う場合ImageプロパティにImage(Bitmap)オブジェクトをセットする使い方をしています。
ただ、ベースとなるコントロールはPaintイベントでGraphicsオブジェクトに対して図形を描画することができるのですが、派生クラスであるPictureBoxでも同様に描画することができます。

なんとなくImageプロパティにセットしたImage(bitmap)オブジェクトに対し描画していると考えていましたが、それだとImageプロパティをセットしない状態で図形を描画した場合どうなるのでしょうか?描画先の画像が無い状態で描画することができないはずですが、どうなるか試してみたいと思います。

namespace PictureBox01;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // ピクチャボックスを生成
        var picbox = new PictureBox()
        {
            Dock = DockStyle.Fill,
            BackColor = Color.Blue, // 背景色を青
            Parent = this,
            // Image = null, // Imageをセットしない
        };
        // ペイントイベント
        picbox.Paint += (s, e) =>
        {
            var g = e.Graphics;
            g.FillRectangle(Brushes.White, 300, 200, 50, 50);
        };
    }
}

実行すると青色の背景に白色の四角形が表示されます。

Imageプロパティにオブジェクトをセットしていない状態で四角形が描画されています。ということはImageプロパティのオブジェクトに対して描画しているわけでは無いようです。

多分ですが、単色の背景のレイヤーがあり、その上にImageプロパティのオブジェクトのレイヤー、その上にGraphicsで描画されるレイヤーといった感じで、基本透明のレイヤーに描画をしていて、描画していない部分が下の層のレイヤーが透過されて見えている考えられます。

今回の場合、1番上の白色の四角形、2番目のImageプロパティのオブジェクトはセットしていないので透過、3番目の背景の青色は白色の四角形以外が透過して見えている状態だと思われます。
 PictureBoxのPaitイベントの都度再描画が行われているはずですので、Paintイベントの前に1番目の背景、2番目のImageプロパティのオブジェクトの再描画が行われていると思われており、その後Paintイベントで透明のGraphicsオブジェクトに対し図形などの描画を行っていると考えられます。

ということはPaintイベントでGraphicsオブジェクトに対して行た描画はPictureBoxのImageプロパティのオブジェクトには反映されていないと思われます。

namespace PictureBox01;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // ピクチャボックスを生成
        var picbox = new PictureBox()
        {
            Dock = DockStyle.Fill,
            BackColor = Color.Blue, // 背景色を青
            Parent = this,
            // Image = null, // Imageをセットしない
        };
        // ビットマップを作成
        Bitmap bmp = new Bitmap(picbox.Width, picbox.Height);
        using(var g = Graphics.FromImage(bmp))
        {
            // 緑色で塗りつぶし
            g.Clear(Color.Green);
        }
        // ビットマップをPictreBoxのImageプロパティに割り当て
        picbox.Image = bmp;
        // ペイントイベント
        picbox.Paint += (s, e) =>
        {
            var g = e.Graphics;
            g.FillRectangle(Brushes.White, 300, 200, 50, 50);
        };
        // フォーム閉じるイベント
        this.FormClosing += (s, e) =>
        {
            // 保存する。
            bmp.Save(@".\sample.png");
        };
    }
}

今度は割り当てたビットマップの緑色ベースに白い四角形が表示されます。

フォームを閉じる際ビットマップを保存した結果、その画像ファイルには白の四角形がありません。

もし四角形を描画した状態の画像が欲しいのであれば、PictureBoxへ行った描画処理を元のビットマップオブジェクトに対しても行う必要があります。

話は変わりますが、PictureBoxのImageプロパティに割り当てたBitmap(Image)オブジェクトは、オブジェクトの参照でしょうか?それともコピー(クローン?)された新しい別オブジェクトでしょうか?確認してみたいと思います。

namespace PictureBox01;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // ピクチャボックスを生成
        var picbox = new PictureBox()
        {
            Dock = DockStyle.Fill,
            BackColor = Color.Blue, // 背景色を青
            Parent = this,
            // Image = null, // Imageをセットしない
        };
        // ビットマップを作成
        Bitmap bmp = new Bitmap(picbox.Width, picbox.Height);
        using(var g = Graphics.FromImage(bmp))
        {
            // 緑色で塗りつぶし
            g.Clear(Color.Green);
        }
        // ビットマップをPictreBoxのImageプロパティに割り当て
        picbox.Image = bmp;
        // フォームロードイベント
        this.Load += (s, e) =>
        {
            // ビットマップへ四角形を描画            
            using (var g = Graphics.FromImage(picbox.Image))
            {
                g.FillRectangle(Brushes.White, 300, 200, 50, 50);
            }
        };
        // フォーム閉じるイベント
        this.FormClosing += (s, e) =>
        {
            // 保存する。
            bmp.Save(@".\sample2.png");
        };
    }
}

フォームのロードイベントのタイミングでPictreuBoxのImageオブジェクトに対して四角形を描画してみました。

四角形が表示されました。
フォームが閉じられてるイベントでビットマップを保存してみました。

こちらにも四角形が描画されていました。
ということですのでPictureBoxのImageプロパティにはBitmap(Image)オブジェクトの参照が割り当てられているようです。
PictureBoxに画像が表示されている場合は参照元のBitmap(Image)オブジェクトをDispose()で破棄すると問題が発生すると思われます。

コメント