【C#】【Windowsフォームアプリケーション】TableLayoutPanelを使ってGUIを構築するぞ

はじめに

なるべくコントロール(ボタンやテキストボックスなど)のサイズや位置を指定しない方法を考えます。

今回設定したのはTableLayoutPanelのサイズ、列数、行数、フォームに対するマージン、各コントロールのフォントのみです。

前回SplitContainerとFlowLayoutPanelを使っていろいろやってみました。
touch-sp.hatenablog.com


今回はTableLayoutPanelを使ってみました。

C#のコード

メインコードとGUI構築のコードを分けて書いています。

GUI構築のコードはフォームがロードされた時に実行されるようになっています。

メインコード

using System;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        private const int marginX = 10;
        private const int marginY = 10;

        private const int TLPWidth = 420;
        private const int TLPHeight = 360;

        private const int row_count = 10;
        private const int column_count = 3;

        public Form1()
        {
            InitializeComponent();
            Load += Form1_load;
        }
        private void Form1_load(object sender, EventArgs e)
        {
            SetClientSizeCore(TLPWidth + 2 * marginX, TLPHeight + 2 * marginY);
            Window_Setting();
        } 
    }
}

GUI構築のコード

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        TableLayoutPanel tlp1 = new TableLayoutPanel();
        float row_percentage;
        float column_percentage;

        Label mainLabel1 = new Label();
        Label mainLabel2 = new Label();

        Button clear_button1 = new Button();
        Button clear_button2 = new Button();

        Button copy_button1 = new Button();
        Button copy_button2 = new Button();

        Label[] labels = new Label[6];
        string[] label_txt = { "変更前", "変更後", "変化量", "結果", "指示量", "結果" };

        TextBox[] txts = new TextBox[6];
        private void Window_Setting()
        {
            row_percentage = (float)100 / row_count;
            column_percentage = (float)100 / column_count;

            for(int i =0; i < row_count; i++)
            {
                tlp1.RowStyles.Add(new RowStyle(SizeType.Percent, row_percentage));
            }
            for(int i =0; i < column_count; i++)
            {
                tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, column_percentage));
            }
            tlp1.Size = new Size(TLPWidth, TLPHeight);
            tlp1.Location = new Point(marginX, marginY);
            Controls.Add(tlp1);

            mainLabel1.Font = new Font("游ゴシック", 12, FontStyle.Bold);
            mainLabel1.Text = "【変更】";
            mainLabel1.Dock = DockStyle.Fill;
            mainLabel1.TextAlign = ContentAlignment.MiddleLeft;
            tlp1.Controls.Add(mainLabel1, 0, 0);

            mainLabel2.Font = new Font("游ゴシック", 12, FontStyle.Bold);
            mainLabel2.Text = "【指示】";
            mainLabel2.Dock = DockStyle.Fill;
            mainLabel2.TextAlign = ContentAlignment.MiddleLeft;
            tlp1.Controls.Add(mainLabel2, 0, 7);

            for (int i = 0; i < 6; i++)
            {
                labels[i] = new Label();
                labels[i].Text = label_txt[i];
                labels[i].Font = new Font("游ゴシック", 11);
                labels[i].Dock = DockStyle.Fill;
                labels[i].TextAlign = ContentAlignment.MiddleCenter;

                txts[i] = new TextBox();
                txts[i].Font = new Font("游ゴシック", 11);
                txts[i].Dock = DockStyle.Fill;
                txts[i].Anchor = AnchorStyles.None;
            }
            tlp1.Controls.Add(labels[0], 0, 1);
            tlp1.Controls.Add(labels[1], 1, 1);
            tlp1.Controls.Add(labels[2], 2, 1);
            tlp1.Controls.Add(labels[3], 0, 4);
            tlp1.Controls.Add(labels[4], 0, 8);
            tlp1.Controls.Add(labels[5], 1, 8);

            tlp1.Controls.Add(txts[0], 0, 2);
            tlp1.Controls.Add(txts[1], 1, 2);
            tlp1.Controls.Add(txts[2], 2, 2);
            tlp1.Controls.Add(txts[3], 0, 5);
            tlp1.Controls.Add(txts[4], 0, 9);
            tlp1.Controls.Add(txts[5], 1, 9);

            clear_button1.Text = "クリア";
            clear_button1.Dock = DockStyle.Fill;
            tlp1.SetRowSpan(clear_button1, 2);
            tlp1.Controls.Add(clear_button1, 2, 4);

            clear_button2.Text = "クリア";
            clear_button2.Dock = DockStyle.Fill;
            tlp1.SetRowSpan(clear_button2, 2);
            tlp1.Controls.Add(clear_button2, 2, 8);

            copy_button1.Text = "コピー";
            copy_button1.Dock = DockStyle.Fill;
            tlp1.Controls.Add(copy_button1, 2, 3);

            copy_button2.Text = "コピー";
            copy_button2.Dock = DockStyle.Fill;
            tlp1.Controls.Add(copy_button2, 2, 7);
        }
    }
}

環境

Windows 11
Visual Studio Community 2022

(補足)オリジナルクラスの作成

以下のようなTableLayoutPanelを継承したオリジナルのクラスを作っておくと便利になります。

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    class OriginalTableLayout: TableLayoutPanel
    {
        private int col_absolute;
        private int row_absolute;
        //コンストラクタ
        public OriginalTableLayout(int colcount, int rowcount, int width, int height)
        {
            col_absolute = width / colcount;
            row_absolute = height / rowcount;

            Size = new Size(col_absolute * colcount, row_absolute * rowcount);

            for(int i = 0; i < colcount; i++)
            {
                ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, (float)col_absolute));
            }

            for(int i = 0; i <rowcount; i++)
            {
                RowStyles.Add(new RowStyle(SizeType.Absolute, (float)row_absolute));
            }
        }
    }
}

メインコードとGUI構築部分のコードはこのように変わります。

メインコード

using System;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        private const int marginX = 10;
        private const int marginY = 10;

        private const int TLPWidth = 420;
        private const int TLPHeight = 360;

        private const int row_count = 10;
        private const int column_count = 3;

        public Form1()
        {
            InitializeComponent();
            Load += Form1_load;
        }
        private void Form1_load(object sender, EventArgs e)
        {
            Window_Setting();
            SetClientSizeCore(tlp1.Width + 2 * marginX, tlp1.Height + 2 * marginY);
        } 
    }
}

GUI構築のコード

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        TableLayoutPanel tlp1 = new OriginalTableLayout(column_count, row_count, TLPWidth, TLPHeight);

        Label mainLabel1 = new Label();
        Label mainLabel2 = new Label();

        Button clear_button1 = new Button();
        Button clear_button2 = new Button();

        Button copy_button1 = new Button();
        Button copy_button2 = new Button();

        Label[] labels = new Label[6];
        string[] label_txt = { "変更前", "変更後", "変化量", "結果", "指示量", "結果" };

        TextBox[] txts = new TextBox[6];
        private void Window_Setting()
        {
            tlp1.Location = new Point(marginX, marginY);
            Controls.Add(tlp1);

            mainLabel1.Font = new Font("游ゴシック", 12, FontStyle.Bold);
            mainLabel1.Text = "【変更】";
            mainLabel1.Dock = DockStyle.Fill;
            mainLabel1.TextAlign = ContentAlignment.MiddleLeft;
            tlp1.Controls.Add(mainLabel1, 0, 0);

            mainLabel2.Font = new Font("游ゴシック", 12, FontStyle.Bold);
            mainLabel2.Text = "【指示】";
            mainLabel2.Dock = DockStyle.Fill;
            mainLabel2.TextAlign = ContentAlignment.MiddleLeft;
            tlp1.Controls.Add(mainLabel2, 0, 7);

            for (int i = 0; i < 6; i++)
            {
                labels[i] = new Label();
                labels[i].Text = label_txt[i];
                labels[i].Font = new Font("游ゴシック", 11);
                labels[i].Dock = DockStyle.Fill;
                labels[i].TextAlign = ContentAlignment.MiddleCenter;

                txts[i] = new TextBox();
                txts[i].Font = new Font("游ゴシック", 11);
                txts[i].Dock = DockStyle.Fill;
                txts[i].Anchor = AnchorStyles.None;
            }
            tlp1.Controls.Add(labels[0], 0, 1);
            tlp1.Controls.Add(labels[1], 1, 1);
            tlp1.Controls.Add(labels[2], 2, 1);
            tlp1.Controls.Add(labels[3], 0, 4);
            tlp1.Controls.Add(labels[4], 0, 8);
            tlp1.Controls.Add(labels[5], 1, 8);

            tlp1.Controls.Add(txts[0], 0, 2);
            tlp1.Controls.Add(txts[1], 1, 2);
            tlp1.Controls.Add(txts[2], 2, 2);
            tlp1.Controls.Add(txts[3], 0, 5);
            tlp1.Controls.Add(txts[4], 0, 9);
            tlp1.Controls.Add(txts[5], 1, 9);

            clear_button1.Text = "クリア";
            clear_button1.Dock = DockStyle.Fill;
            tlp1.SetRowSpan(clear_button1, 2);
            tlp1.Controls.Add(clear_button1, 2, 4);

            clear_button2.Text = "クリア";
            clear_button2.Dock = DockStyle.Fill;
            tlp1.SetRowSpan(clear_button2, 2);
            tlp1.Controls.Add(clear_button2, 2, 8);

            copy_button1.Text = "コピー";
            copy_button1.Dock = DockStyle.Fill;
            tlp1.Controls.Add(copy_button1, 2, 3);

            copy_button2.Text = "コピー";
            copy_button2.Dock = DockStyle.Fill;
            tlp1.Controls.Add(copy_button2, 2, 7);
        }
    }
}