【入門編】Windows FormsのMDI(マルチドキュメントインターフェイス)設計とタブ化:MdiClientのカスタマイズによるモダンなIDE風画面構築 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは!
マクロの記録や単純なフォームの貼り付け作業から一歩進んで、「おっ、プロっぽいアプリを作ってみたい!」と思っているあなたへ。

今回は、Windows Forms(Windowsフォーム)アプリ開発の現場で、長年「ちょっと古いよね…」と言われがちだったMDI(マルチドキュメントインターフェイス)を、現代のVisual StudioやGoogle Chromeのように「タブ化された洗練されたIDE風UI」へと生まれ変わらせる極意を伝授します。

「複数の子画面がバラバラに散らばって管理しにくい」「レガシーな見た目を何とかしたい」という悩みを、VB.NETの力で鮮やかに解決していきましょう。
ここをクリアすれば、あなたのWindows Formsアプリ開発のスキルは間違いなく一段階上のステージに到達します。一緒にマスターしていきましょう!

—

1. なぜレガシーMDIは敬遠されるのか?

Visual StudioのWindows Formsデザイナで親ウィンドウ(メインフォーム)の `IsMdiContainer` プロパティを `True` にすると、簡単に複数画面を抱えるMDI親フォームが作れます。

しかし、そのままでは子ウィンドウがバラバラと重なり合ったり、最小化するとアイコンが親フォームの底に沈んでしまったりと、今の時代には少し使い勝手が悪い代物です。

現代風UI(タブ切り替え型)のメリット

  • 画面の視認性が飛躍的に向上する:ブラウザのようにタブで切り替えられるため、今どの作業を開いているかが一目瞭然。
  • デスクトップスペースの有効活用:ウィンドウが勝手に重なって隠れることがない。
  • プロフェッショナルな外観:ユーザーに「おっ、ちゃんとしたシステムだ!」と直感的に感じさせられる。

これを実現するために、標準の `MdiClient`(MDIの裏側で子ウィンドウを統括している見えないコンテナ)の挙動をVB.NETから巧みにハック(制御)していきます。

—

2. 全体設計とアプローチ

Visual Studio標準のコンポーネントだけでこれを完璧にやろうとすると少し工夫が必要です。一般的には、以下の構成をとります。

1. メインフォーム(`MainForm`):`IsMdiContainer = True` に設定しつつ、上部に `TabControl` を配置。
2. サブウィンドウ(`ChildForm`):開かれるたびにタブと連動させる。
3. MdiClientのサブクラス化 / 制御:子ウィンドウが閉じられたときやアクティブになったときのイベントをタブと同期させる。

今回は、もっとも直感的かつ実務で使える「TabControlとMDIの完全同期テクニック」のコードをVB.NETで解説します。

—

3. 実装コード:モダンIDE風タブMDIの構築

それでは、実際のプロジェクトに組み込めるVB.NETのコードを見ていきましょう。
今回は、メインフォームに `MenuStrip`(メニュー)、`TabControl`(タブ)、そしてMDI領域を持つサンプルです。

メインフォーム(`MainForm.vb`)のコード

Public Class MainForm

‘ フォームが読み込まれたときの処理
Private Sub MainForm_Load(sender As Object, eEventArgs) Handles MyBase.Load
‘ MDIクライアント領域の色を微調整するなど、初期設定をここに書きます
Me.Text = “モダンIDE風 MDIサンプル”
Me.WindowState = FormWindowState.Maximized

‘ TabControlの設定(タブを閉じられるようにする等の調整も可能)
TabControl1.Dock = DockStyle.Fill
End Sub

‘ 「新規ファイル作成」メニューがクリックされたとき
Private Sub mnuNewFile_Click(sender As Object, e As EventArgs) Handles mnuNewFile.Click
‘ 新しい子フォームのインスタンスを作成
Dim child As New ChildForm()

‘ 親を自分(MainForm)に設定
child.MdiParent = Me

‘ 子フォームに対応するタブページを作成
Dim tabPage As New TabPage(child.Text)
tabPage.Tag = child ‘ タブと子フォームを「Tag」プロパティで紐付ける!ここが最大のポイント

‘ TabControlに追加して選択状態にする
TabControl1.TabPages.Add(tabPage)
TabControl1.SelectedTab = tabPage

‘ 子フォーム側のイベント(閉じられたとき等)を購読
AddHandler child.FormClosed, AddressOf ChildForm_FormClosed

‘ 子フォームを表示
child.Show()
End Sub

‘ 子フォームが閉じられたときの同期処理
Private Sub ChildForm_FormClosed(sender As Object, e As FormClosedEventArgs)
Dim closedChild As ChildForm = CType(sender, ChildForm)

‘ 対応するタブページを探して削除する
For Each tabPage As TabPage In TabControl1.TabPages
If CType(tabPage.Tag, ChildForm) Is closedChild Then
TabControl1.TabPages.Remove(tabPage)
Exit For
End If
5 Next
End Sub

‘ タブが切り替わったときに、対応するMDI子ウィンドウをアクティブにする
Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged
If TabControl1.SelectedTab IsNot Nothing Then
Dim targetChild As ChildForm = CType(TabControl1.SelectedTab.Tag, ChildForm)
If targetChild IsNot Nothing Then
targetChild.Activate()
End If
End If
End Sub

‘ ユーザがタブの閉じるボタン(またはUI)でタブを消そうとしたときの連動
‘ ※簡易的な実装として、タブが消されたら子フォームも閉じる処理
Private Sub TabControl1_ControlRemoved(sender As Object, e As ControlEventArgs) Handles TabControl1.ControlRemoved
‘ 必要に応じてタブ側の操作から子フォームを閉じるロジックをここに追加します
End Sub

End Class

—

4. 初学者が陥りやすい罠とエラー回避の知見

ここをクリアすればバッチリ!というポイントを、現場のエンジニア目線で解説します。

① `Tag` プロパティの型キャスト(Cast)エラー

上記のコードでは、`TabPage.Tag` に子フォームのインスタンス(`ChildForm`)を格納しています。
VB.NETで `Option Strict On`(厳格モード)を設定している場合、`CType(tabPage.Tag, ChildForm)` のように明示的な型変換が必要です。これを怠ると実行時エラー(InvalidCastException)の元になります。
> 知見: オブジェクトの紐付けには `Tag` プロパティが非常に便利ですが、何が入っているか型を意識する癖をつけましょう。

② イベントの多重登録・メモリリーク

子フォームを閉じたときに `RemoveHandler` を忘れたり、インスタンスの参照が残ったままだと、ガベージコレクション(GC)が働かずにメモリリーク(メモリの無駄遣い)を引き起こします。
`FormClosed` イベントでしっかりと結びつきを解除し、不要になったオブジェクトの参照を断ち切る意識を持ちましょう。

③ MDIウィンドウの背景色問題

デフォルトの `MdiClient` は、なぜか少し古臭いグレーの背景色をしています。これをモダンなダークモード風やフラットな白背景に変えたい場合、少し高度になりますが `MdiClient` コレクションをループして背景色をペイントし直すテクニックが必要になります。まずは標準のままでレイアウトの同期をマスターすることから始めましょう。

—

5. おわりに

いかがでしたでしょうか?
今回は、レガシーになりがちなWindows FormsのMDIを、`TabControl` と美しく連動させてモダンなIDE風に仕立て上げる設計手法を解説しました。

「Visual Basicは古い言語だ」と言われることもありますが、Windowsのネイティブな仕組みをダイレクトに叩けるWindows Formsは、業務アプリの高速開発において今なお最強の武器の一つです。こうした細やかなUIのこだわりを実装できるようになると、周りからの評価もガラリと変わります。

一つひとつのコードの意味を噛み締めながら、ぜひご自身の開発環境でも試してみてください。
あなたのVB.NETライフが、より一層エキサイティングなものになることを応援しています!

タイトルとURLをコピーしました