C# パネルをいくつか配置し、それぞれにコントロールやグラフィクス、イメージを表示する。

　Formの上に、パネルをいくつか配置し、それぞれの上にコントロールやグラフィクス、イメージを表示したみた。
[![dbs1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501068/d52074cd-b9e5-0af7-19cc-0929cfa2108b.gif)](
https://dobon.net/vb/dotnet/graphics/creategraphics.html)
　そもそもは、[Dobon.net](
https://dobon.net/vb/dotnet/graphics/creategraphics.html)に記述されていたコード ”Panel1.Invalidate();” の意味が分からず、”Invalidate()”の前は、ふつう”this”じゃないの、、、と思いつつ、、、

　数日悩んだあげく、やっと ”Invalidate()” の前には、再描画させたいパネル（領域）を指定するということに気が付いた。

　というわけで、このソースには Invalidate() が２つ、Panelが３つ含まれている。
　また、おかげでPenelの上に、コントロール、グラフィクス、イメージの表示のさせ方がわかった。

![動作画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501068/1b81e83a-f6ff-2108-d0b4-19a3d7be567a.png)


```cs
// https://dobon.net/vb/dotnet/graphics/creategraphics.html
// 高橋麻奈著　やさしいC#　p211,222　SBCreative

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Project1
{
    class Class1 : Form
    {
        // 変数の宣言と代入
        //画像ファイルを読み込む
        Image[] images = new Image[] {
                                        Image.FromFile(@"C:\materials\picture\car100_50.bmp"),
                                        Image.FromFile(@"C:\materials\picture\racingcar100_50.bmp")
                                     };
        Image currentImage = null;
        Image backImage = Image.FromFile(@"C:\materials\picture\thankful640_640.jpg");

        // ラベルの宣言
        Label lb0, lb1, lb2, lb3;

        // フロアパネルの宣言
        Panel panel1, panel2, panel3;

        // ボタンの宣言
        Button button1;

        // パネル３の上でマウスクリックしたときに、その位置を記憶するリストの宣言
        private List<Point> ls;

        // メインメソッド
        public static void Main()
        {
            Application.Run(new Class1());
        }

        // コンストラクタ
        public Class1()
        {
            // ウインドウの定義
            Text = "Panelをいくつか配置し、グラフィックス、コントロール、イメージを表示する";
            Width = 640;
            Height = 640;

            //パネル３の上でマウスクリックしたときに、その位置を記憶するリスト
            ls = new List<Point>();


            // パネル1（領域１）の定義
            panel1 = new Panel();
            panel1.BorderStyle = BorderStyle.FixedSingle;   //境界線
            panel1.Location = new Point(300, 300);
            panel1.Size = new Size(100, 100);
            panel1.BackColor = Color.Gray;
            this.Controls.Add(panel1);

            // パネル2（領域３）の定義
            panel2 = new Panel();
            panel2.BorderStyle = BorderStyle.FixedSingle;   //境界線
            panel2.Location = new Point(100, 200);
            panel2.Size = new Size(200, 100);
            this.Controls.Add(panel2);

            // パネル3（領域３）の定義
            panel3 = new Panel();
            panel3.BorderStyle = BorderStyle.FixedSingle;   //境界線
            panel3.Location = new Point(0, 400);
            panel3.Size = new Size(300, 200);
            this.Controls.Add(panel3);

            // ボタン1の定義
            button1 = new Button();
            button1.Text = "ボディーカラー変更\nこの赤いボタンを押してください。";
            button1.AutoSize = true;
            button1.Dock = DockStyle.Bottom;
            button1.BackColor = Color.Red;
            panel2.Controls.Add(button1);

            // ラベル0の定義
            lb0 = new Label();
            lb0.ForeColor = Color.Blue;
            lb0.BackColor = Color.Yellow;
            lb0.Text = "thisの領域";
            this.Controls.Add(lb0);

            // ラベル1の定義
            lb1 = new Label();
            lb1.Text = "panel1の領域";
            panel1.Controls.Add(lb1);

            // ラベル２の定義
            lb2 = new Label();
            lb2.Text = "panel2の領域";
            panel2.Controls.Add(lb2);

            // ラベル２の定義
            lb3 = new Label();
            lb3.AutoSize = true;
            lb3.Text = "panel3の領域。\nこの領域でクリックしてください";
            panel3.Controls.Add(lb3);

            // 画像の初期化
            currentImage = images[0];

            //ボタン１のイベントハンドラの登録
            button1.Click += new EventHandler(Button1_Click);

            //Panel1_Paintで記述された内容を、Panel1に描画するためにイベントハンドラを登録する
            this.Paint += new PaintEventHandler(Back_Paint);

            //Panel1_Paintで記述された内容を、Panel1に描画するためにイベントハンドラを登録する
            panel1.Paint += new PaintEventHandler(Panel1_Paint);

            panel3.MouseDown += new MouseEventHandler(Panel3_MouseDown);
            panel3.Paint += new PaintEventHandler(Panel3_Paint);
        }

        // Panel1のPaintイベントハンドラ
        private void Panel1_Paint(Object sender, PaintEventArgs e)
        {
            if (currentImage != null)
            {
                // DrawImageメソッドで画像をpanel1の座標系の(0, 25)の位置に表示する
                Graphics g = e.Graphics;
                g.DrawImage(currentImage, 0, 25, currentImage.Width, currentImage.Height);
            }
        }

        // thisのPaintイベントハンドラ
        private void Back_Paint(Object sender, PaintEventArgs e)
        {
            if (backImage != null)
            {
                //DrawImageメソッドで画像を示する
                Graphics g = e.Graphics;
                g.DrawImage(backImage, 0, 0, backImage.Width, backImage.Height);
            }
        }

        //Button1のClickイベントハンドラ
        private void Button1_Click(object sender, EventArgs e)
        {
            //表示する画像を入れ替える
            if (currentImage != images[0])
            {
                currentImage = images[0];
            }
            else
            {
                currentImage = images[1];
            }
            //コントロールを再描画する。これがないと、新しい画像が表示されない。
            this.Invalidate();
            panel1.Invalidate();  //panel1に対してのみ、グラフィックスをInvalidate()する。
        }

        // Panel3でマウスをクリック（ダウン）したときのイベントハンドラ
        public void Panel3_MouseDown(Object sender, MouseEventArgs e)
        {
            Point p = new Point();
            p.X = e.X;
            p.Y = e.Y;
            ls.Add(p);
            panel3.Invalidate();
        }

        // Panel3で描画するためのイベントハンドラ
        public void Panel3_Paint(Object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen dp = new Pen(Color.Pink, 3);

            foreach (Point p in ls)
            {
                g.DrawEllipse(dp, p.X - 5, p.Y - 5, 10, 10);
            }
        }
    }
}


```


# 最後に
本記事を作成後4年余り過ぎて初めてストックされました。（感動）
しかし、久しぶりに見て驚き、この記事は20,000人もの人が閲覧してくださっている。驚きだ。しかし、20,000人もの人が見て、初めてのストックとはなんとも情けない。検索ワードとしては引っかかるのだが、内容が詰まらないのだろう。

さて、C#の勉強を続ければ、次のようなアプリが作れるようになります。
[語学学習用アプリの開発（途中）](https://qiita.com/guijiu/items/f7382ca825e126c2b436)
[役に立たない定規をつくる](https://qiita.com/guijiu/items/226b71957401c08dac09)
2024年10月6日追記