26: VisualC++で複数のフォームでタブ切り替え

概要

前回の記事 から作成しているGUIチートクライアントにおいて、サイドバーの項目をクリックする事でコンテンツウィンドウに表示されるフォームを切り替えます。 これを実現するには、各項目用のフォームをそれぞれ用意し、ボタンクリックイベントでそのフォームを切り替えます。
今回は、GUIチートクライアントのサイドバーの項目をクリックする事により、コンテンツウィンドウに表示されるフォームを切り替える事を目標にやっていきます。
チート対象のゲームは、x86でチートの練習用に作られた、Pwn Adventure 3を使います。
Windows対象で、Visual Studio 2019を使用しC++/CLIで記述する。ソースコードはまとめてページの一番下にある。

三つの項目用のフォームを作成

現状「Player」「Warp」「Item」の三つの項目があるので、それぞれ用のフォームを作成する。
以下のようにして新しい項目を追加する画面を出しましょう。 そして、以下のようにUI > Windowsフォームから追加しましょう。 同様の手順で「Warp」「Item」のフォームも作成しましょう。

作り終えたら、今度は見た目を整えます。
全てのフォームのプロパティにおいて、以下を設定しましょう。
※ 注意としてSizeは他のプロパティ項目を変える事で値が変わる場合があるので、一番最後に設定するのが良いです。

フォームの切り替え

では、サイドバーのボタンクリックイベントによりフォームを切り替えるコードを書いていきます。
MainWindow.hを開くと、既に色々なコードが自動生成されていると思います。 自動生成されたコードは #pragma region ~ #pragma endregion の間に書かれているので、 これから追加するコードは自動生成されたコードの下、すなわち #pragma endregion の下に書いていきます。
でも、まずはMainWindow.h内で上記で作成した各フォームを扱えるように、各フォームのヘッダファイルをincludeしましょう。
そして、#pragma endregion の下に以下のように書きましょう。 まず、最初の三行で各フォームのインスタンスを生成しています。
その後の switchForm関数はコンテンツウィンドウに表示するフォームを切り替えるための関数です。
activeFormが現在表示されてるフォームを格納するものです。 この関数が呼ばれた場合、現在表示されてるフォームをactiveForm->Hide()で隠し、 新しいフォームをactiveForm = factiveFormにセットします。
その後、そのフォームを表示するための色々な設定をしていますが、その各種コードの意味を以下に示します。
書けたら、一旦MainWindow.hのデザインビューの方に行き、サイドバーにあるPlayerボタンをダブルクリックしましょう。
そうすると、MainWindow.hのソースコードの方に飛び、以下のようなボタンクリックのイベントハンドラーが自動生成されるはずです。 同様にして「Warp」「Item」の方のイベントハンドラーも追加し、中にこのように書きましょう。
これで実際に試してみたいですが、現状フォームは全部同じデザインでこれだと切り替わってるかどうかわからないので、 適当にボタンとか置いて切り替わってるかどうかを確認しましょう。切り替わったら成功です。

ソースコード

MainWindow.hに追加するフォーム切り替え用のコード

private:
    Form^ warpwnd   = gcnew WarpWindow();
    Form^ playerwnd = gcnew PlayerWindow();
    Form^ itemwnd   = gcnew ItemWindow();

    Form^ activeForm = nullptr;
    void switchForm(Form^ f) {
        if (activeForm != nullptr)
            activeForm->Hide();
        activeForm = f;
        f->TopLevel = false;
        f->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
        f->Dock = DockStyle::Fill;
        ContentPanel->Controls->Add(f);
        ContentPanel->Tag = f;
        f->BringToFront();
        f->Show();
    }

private: System::Void PlayerSideBarButton_Click(System::Object^ sender, System::EventArgs^ e) {
    switchForm(playerwnd);
}
private: System::Void WarpSideBarButton_Click(System::Object^ sender, System::EventArgs^ e) {
    switchForm(warpwnd);
}
private: System::Void ItemSideBarButton_Click(System::Object^ sender, System::EventArgs^ e) {
    switchForm(itemwnd);
}
};