フォームを開いたら元のフォームを閉じたい(つまりメインフォームを切り替えたい)

またまたWindowsフォームの話になります。例えば、メニューのフォームがあってそこから別のフォームを起動したら元のメニューのフォームは閉じたい。なんていうときの話です。
イメージはこんな感じ☟

これを実現するには、いくつかやり方があると思います。例えば、メニューだけのアプリ(exe)を作って、そこからProcess.Startとかして子フォーム用のまったく別のアプリを起動する方法なんてのもあるかと思います。が、今回は1つアプリで実現する方法を考えてみたいと思います。

やる内容をざっと説明すると、アプリケーションのエントリポイントで、Formの代わりにApplicationContextを使ってApplication.Runする方法になります。

①まず、Windowsフォームの空っぽのプロジェクトを作成。Form1はもともとあるので、Form2~Form4を追加します。

②Program.csを開き、次のように編集します。

namespace WinFormsApp1
{
    internal static class Program
    {
        public static ApplicationContext AppCon;

        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.
            ApplicationConfiguration.Initialize();
            //Application.Run(new Form1());

            AppCon = new ApplicationContext();
            AppCon.MainForm = new Form1();
            Application.Run(AppCon);
        }
    }
}

③Form1に3つボタンを配置して、そのクリックイベントに子フォームを開いて、自分のフォームを閉じるコードを書きます。

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

        private void Form2_button_Click(object sender, EventArgs e)
        {
            Program.AppCon.MainForm = new Form2();
            Program.AppCon.MainForm.Show();
            this.Close();
        }

        private void Form3_button_Click(object sender, EventArgs e)
        {
            Program.AppCon.MainForm = new Form3();
            Program.AppCon.MainForm.Show();
            this.Close();
        }

        private void Form4_button_Click(object sender, EventArgs e)
        {
            Program.AppCon.MainForm = new Form4();
            Program.AppCon.MainForm.Show();
            this.Close();
        }
    }
}

これで終わりです。実行してみてください。ボタンを押すと最初のメニューのフォームが消え子フォームだけになりませんか?


余談ですが、Program.cs内のApplicationContextをForm1側で直接いじるのが嫌な人は、次の例のようにSwitchFormのようなメソッドを作っても良いかもしれません。

namespace WinFormsApp1
{
    internal static class Program
    {
        private static ApplicationContext AppCon;

        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.
            ApplicationConfiguration.Initialize();
            //Application.Run(new Form1());

            AppCon = new ApplicationContext();
            AppCon.MainForm = new Form1();
            Application.Run(AppCon);
        }

        public static void SwitchForm(Form f)
        {
            AppCon.MainForm = f;
            AppCon.MainForm.Show();
        }
    }
}
namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form2_button_Click(object sender, EventArgs e)
        {
            Program.SwitchForm(new Form2());
            this.Close();
        }

        private void Form3_button_Click(object sender, EventArgs e)
        {
            Program.SwitchForm(new Form3());
            this.Close();
        }

        private void Form4_button_Click(object sender, EventArgs e)
        {
            Program.SwitchForm(new Form4());
            this.Close();
        }
    }
}

コメント