Winフォームアプリで、クリックするたびに反転するボタンを作ってみる

ベースとなるコードは次のページのものを使っていますので、まずこちらを進めてください

Formクラスだけでの実現

クリックするたびに反転するボタンのイメージは次のようになります
クリックするたびに反転しています

実行イメージ

コード

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

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

            button1.ForeColor = Color.Black;
            button1.BackColor = Color.White;
            button2.ForeColor = Color.Black;
            button2.BackColor = Color.White;
            button3.ForeColor = Color.Black;
            button3.BackColor = Color.White;
        }

        private void ColorChangeEventHandler(object sender, EventArgs e)
        {
            Button button = (Button)sender;

            if (button.ForeColor == Color.Black)
            {
                button.BackColor = Color.Black;
                button.ForeColor = Color.White;
                return;
            }

            button.BackColor = Color.White;
            button.ForeColor = Color.Black;
        }
    }
}

マイボタンのクラスを作って実現

コード

次のようにクラスを作ってみましょう
ポイントは、Buttonクラスの継承にあります
このMyButtonクラスは、Buttonクラスを継承しているのでButtonクラスでできることは全てできます
元々のButtonクラスにさらに反転機能を持たせた新しい機能アップされたクラスを作るイメージですね
まず、最初は、初期の色を変更しておきます(コンストラクタに記述)

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

namespace ButtonEventSample
{
    internal class MyButton : Button
    {
        public MyButton()
        {
           ForeColor = Color.Black;
           BackColor = Color.White;
        }
    }
}

マイボタンを自作のコントロールにする

メニューからソリューションをビルドします

ツールボックスの自作コントロールを配置

フォーム上にMyButtonを配置してみましょう
プロパティを確認すると、ForeColorとBackColorの初期値がセットされているのがわかります

押している状態を保持するように自作ボタンを更新

IsPressedプロパティをMyButtonクラスに追加して、状態(押されていれば true、そうでなければ false)を保持できるようにします

public bool IsPressed { get; set; }

状態により色を変えるためにプロパティをさらに更新します
他のクラスから、IsPressedプロパティをセットすることでも色を変えることができるようになります

bool isPressed;

public bool IsPressed
{
    get
    {
        return isPressed;
    }
    set
    {
        isPressed = value;

        if (isPressed)
        {
            ForeColor = Color.White;
            BackColor = Color.Black;
        }
        else
        {
            ForeColor = Color.Black;
            BackColor = Color.White;
        }
    }
}

クリックされるたびに反転するように自作クラスを更新

MyButtonに反転機能も持たせます

Click += ColorChangeEventHandler;

private void ColorChangeEventHandler(object sender, EventArgs e)
{
    IsPressed = !IsPressed;
}

これまでのコードをまとめる

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

namespace ButtonEventSample
{
    internal class MyButton : Button
    {
        public MyButton()
        {
            ForeColor = Color.Black;
            BackColor = Color.White;

            Click += ColorChangeEventHandler;
        }

        private void ColorChangeEventHandler(object sender, EventArgs e)
        {
            IsPressed = !IsPressed;
        }

        bool isPressed;

        public bool IsPressed
        {
            get
            {
                return isPressed;
            }
            set
            {
                isPressed = value;

                if (isPressed)
                {
                    ForeColor = Color.White;
                    BackColor = Color.Black;
                }
                else
                {
                    ForeColor = Color.Black;
                    BackColor = Color.White;
                }
            }
        }
    }
}

Form1側のコードを合わせて更新

ボタン1からボタン3のオブジェクト(インスタンス)は削除しています

using System.Windows.Forms;

namespace ButtonEventSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

実行結果

ボタン1からボタン3は削除しています

MyButtonを3つ並べて、実行してみましょう

ただ、ツールボックスからドラッグ&ドロップするだけです
あたかも、既にあるButtonコンポーネントを使うようにするだけです

実行結果

応用

今のボタンの状態(押されている?押されていない)を読み取ってみましょう

IsPressedプロパティの確認

作成したIsPressedプロパティは、プロパティ画面にも表示されるようになります

ボタンの状態で、ボタンのテキストが変わるようにしてみましょう

フォーム画面でmyButton1を選択して、Clickイベントを追加して次のコードを書いてみましょう

コード

using System.Windows.Forms;

namespace ButtonEventSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void MyButtonClick(object sender, System.EventArgs e)
        {
            MyButton myButton = (MyButton)sender;

            if (myButton.IsPressed)
            {
                myButton.Text = "押されている";
                return;
            }

            myButton.Text = "押されていない";
        }
    }
}

他のボタンにこのイベントハンドラを登録する

前回のページで説明したように他のボタンにも同じイベントハンドラを割り当ててみましょう

実行結果

リファクタリング

MyButtonはサンプルとしてはいいのですが、せっかくなので、意味のあるクラス名にしたいところです
例えば、反転ボタンということで「ReverseButton」がいいでしょう

関連するいろいろなところを間違いなく変更しなければならないのでインテリセンスに任せてみます
このように後からネーミングがふさわしくないと思ったら、どんどん変更していきましょう
(念の為、変更前にはGitでコミットしておきましょう)

クラス名の変更

続いて、ファイル名を変更

最後にソリューションのビルド

デザイン画面で確認