【実務・中級編】ToolStripManagerとSettingsによるツールバーカスタマイズの永続化:ユーザーごとのドッキング位置と表示状態の保存 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

ToolStripManagerとSettingsの極意:ユーザーごとのツールバー状態永続化を実装する

Windows Forms(WinForms)による業務アプリケーション開発において、エンドユーザーからの「要望」で最も多いものの一つが、「ツールバーのレイアウトやドッキング位置を記憶してほしい」という要件だ。

開発初期の段階では、デフォルトのドッキング位置で満足していても、現場で実務をこなすにつれて、ユーザーは自分の利き手や作業フローに合わせてメニューバーを左右に寄せたり、特定のツールバーをフローティングさせたり、不要な項目を非表示にしたりしたくなる。

これを毎回手動で戻させるようなUI設計をしているとしたら、それはアプリケーションの設計ミスであり、ユーザーの業務効率を著しく阻害していると言わざるを得ない。

今回は、VB.NETの `System.Windows.Forms.ToolStripManager` と アプリケーション設定 (`My.Settings`) を完全に掌握し、「バグを踏まない、一撃で完璧にレイアウトを永続化・復元するメカニズム」を伝授する。

—

なぜ従来の安易な実装では破綻するのか?

多くの初学者や、場当たり的なコーディングを行うプログラマは、各 `ToolStrip` の `Dock` プロパティや `Visible` プロパティを個別に `My.Settings` へ保存しようとする。

‘ 【アンチパターン】絶対にやってはいけない個別保存
My.Settings.Toolbar1_Top = ToolStrip1.Top
My.Settings.Toolbar1_Visible = ToolStrip1.Visible
‘ これをフォーム上の全てのツールバーに対して書く…

このアプローチは悪夢の始まりである。
将来的にツールバーを追加・削除したり、動的に生成する設計変更が入った瞬間、設定のスキーマが破綻し、インデックスがズレ、最悪の場合は起動時に NullReferenceException の嵐に見舞われることになる。

究極の解決策:ToolStripManagerの活用

.NET Frameworkには、この「ツールバーの迷宮」を鮮やかに解決するための専用クラスが標準で用意されている。それが `ToolStripManager` だ。

`ToolStripManager` を使えば、フォーム上の全ての `ToolStrip` の状態(ドッキング位置、フローティング状態、表示/非表示、サイズ、アイテムの順序まで)を、たった数行のシリアライズされた文字列として一括管理できる。

—

実装アーキテクチャの全体像

堅牢な永続化システムを構築するためには、以下のライフサイクルを厳守する必要がある。

1. 復元(Load時): フォームの初期化が完了し、`ToolStrip` 群がインスタンス化された直後(`Form_Load` の後半)に状態を流し込む。
2. 保存(FormClosing時): ユーザーがアプリケーションを終了する際、フォームが破棄される直前に状態をキャプチャし、永続化レイヤーに書き出す。

それでは、実際のプロダクションコードを見ていこう。

—

プロダクションコード例 (VB.NET)

以下のコードは、そのままプロジェクトに組み込んで即座に実用できる、堅牢な実装である。

前提条件

Visual Studioのプロジェクトプロパティから「設定 (Settings)」タブを開き、以下の設定を追加しておく。

  • 名前: `ToolStripState`
  • 型: `String`
  • スコープ: `User`

フォーム側の実装コード

Public Class MainForm

Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
‘ 1. ユーザー固有のレイアウト設定を復元する
LoadToolbarState()

Catch ex As Exception
‘ 復元失敗時はログに記録し、デフォルトレイアウトで続行させる(例外でアプリを落とさない)
System.Diagnostics.Debug.WriteLine($”ツールバー復元エラー: {ex.Message}”)
‘ 必要に応じてデフォルト状態にリセットする処理をここに記述
End Try
End Sub

Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
Try
‘ 2. 現在のレイアウト状態をキャプチャして永続化する
SaveToolbarState()

Catch ex As Exception
‘ 保存失敗がアプリケーション終了をブロックしないようにする
System.Diagnostics.Debug.WriteLine($”ツールバー保存エラー: {ex.Message}”)
End Try
End Sub

”’

”’ ツールバーの配置状態をSettingsから読み込み、フォームに適用する
”’

Private Sub LoadToolbarState()
‘ My.Settings.ToolStripState に保存された文字列が存在するかチェック
Dim savedState As String = My.Settings.ToolStripState

If Not String.IsNullOrEmpty(savedState) Then
‘ ToolStripManagerを使用して、フォーム全体のツールバー状態を復元
‘ 引数には「フォームの型名」をプレフィックスとして渡すのがベストプラクティス(複数フォーム対応)
Dim settingsKey As String = Me.GetType().FullName

‘ 既存の設定適用
‘ 注意: フォーム内のすべての ToolStrip コントロールがマネージャーに登録されている必要がある
ToolStripManager.LoadSettings(Me, settingsKey)
End If
End Sub

”’

”’ フォーム内のツールバー配置状態をキャプチャし、Settingsへ保存する
”’

Private Sub SaveToolbarState()
Dim settingsKey As String = Me.GetType().FullName

‘ ToolStripManagerに現在の状態をキャプチャさせる
ToolStripManager.SaveSettings(Me, settingsKey)

‘ アプリケーション設定へコミット(ディスクへの書き込み)
My.Settings.Save()
End Sub

End Class

—

現場で役立つチーフアーキテクトからの重要アドバイス

この実装を導入するにあたり、プロの現場でハマりがちな「罠」と、その回避策を共有しておこう。

1. フォームの型名をキーにする理由

複数画面(MDI親フォームや複数の子ウィンドウ)を持つアプリケーションの場合、`ToolStripManager.SaveSettings(Me)` のシグネチャを安易に使うと、設定のキーが競合し、他の画面のレイアウトを上書きしてしまう事故が起きる。
必ず `Me.GetType().FullName`(または一意に識別できる文字列)をキーとして明示的に渡す設計にすること。

2. 動的に追加される ToolStrip への配慮

もしアプリケーションの起動後、ユーザーの権限や動的なデータバインドによって `ToolStrip` コントロールが後から動的に生成・追加される場合、`LoadToolbarState` を呼び出すタイミングは「全ての ToolStrip の生成とフォームへのコントロール追加が完全に終わった後」でなければならない。
タイミングを誤ると、保存されていた設定データの宛先が見つからず、レイアウトが崩壊する原因になる。

3. 設定ファイルが破損したときの「逃げ道」

ユーザーのPC環境の異常終了やディスク容量不足などにより、`user.config` が破損することが稀にある。
このような場合、起動時に `ConfigurationErrorsException` がスローされることがあるため、アプリケーションのエントリーポイント(`Application_ThreadException` や `AppDomain.CurrentDomain.UnhandledException`)で例外を捕捉し、破損した設定ファイルを自動削除(`My.Settings.Upgrade()` やファイル削除)してデフォルト起動させるフォールバック機構を組んでおくと、ヘルプデスクへの問い合わせを劇的に減らすことができる。

—

まとめ

業務アプリケーションの価値は、「にいのまゝに動くこと」だけでなく、「ユーザーのストレスを極限まで排除し、日々のルーティンワークを加速させること」にある。

たったこれだけのコード、たったこれだけの設計思想を取り入れるだけで、アプリケーションの「プロダクトとしての格」は一段と跳ね上がる。
ぜひあなたのプロジェクトでもこの実装を取り入れ、ワンランク上のWindows Formsアプリケーションを構築してほしい。

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