# 画面設計書 14-プロパティページホストダイアログ

## 概要

本ドキュメントは、プロパティページをダイアログとしてホスト（表示）するための「プロパティページホストダイアログ」の画面設計を記載します。

### 本画面の処理概要

**業務上の目的・背景**：プロパティページホストダイアログは、Visual Studio のプロジェクトプロパティページを独立したダイアログウィンドウとして表示するためのコンテナです。通常、プロパティページはプロジェクトデザイナー内のタブとして表示されますが、特定のシナリオでは個別のダイアログとして表示する必要があります。このダイアログは PropPageUserControlBase を継承したプロパティページを動的にホストし、OK/Cancel ボタンによる変更の適用/キャンセル機能、F1 ヘルプ機能を提供します。

**画面へのアクセス方法**：このダイアログは直接アクセスするものではなく、プロパティページをダイアログとして表示する必要がある場合にプログラム的に呼び出されます。PropPageUserControlBase の子ページ機能などで使用されます。

**主要な操作・処理内容**：
1. プロパティページのホスト：PropPage プロパティを通じて PropPageUserControlBase を受け取り、ダイアログ内に表示
2. OK ボタンによる確定：変更があれば Apply() を呼び出し、ダイアログを閉じる
3. Cancel ボタンによるキャンセル：RestoreInitialValues() を呼び出し変更を復元、ダイアログを閉じる
4. ヘルプボタンによるヘルプ表示：ホストされたプロパティページの F1 キーワードを使用してヘルプを表示
5. サイズ変更対応：ホストされたページの PageResizable プロパティに応じてリサイズを許可

**画面遷移**：
- この画面への遷移元：PropPageUserControlBase を使用するプロパティページ（子ページ表示時など）
- この画面からの遷移先：なし（OK / Cancel で呼び出し元に戻る）

**権限による表示制御**：ホストされるプロパティページの権限に依存します。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 48 | MSBuildタスク（Fsc） | 補助機能 | 個別のプロパティページをダイアログとして表示するコンテナ |

## 画面種別

ダイアログ（モーダル）

## URL/ルーティング

Visual Studio 内のダイアログとして動作するため、URL/ルーティングは存在しません。

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|-----------|----------|------|------|
| PropPage | 入力 | PropPageUserControlBase | はい | ホストするプロパティページ |
| ServiceProvider | 入力 | IServiceProvider | はい | Visual Studio サービスプロバイダー |
| F1Keyword | 入力 | String | いいえ | ヘルプ用 F1 キーワード |

## 表示項目

| コントロール名 | 種類 | 説明 | データバインド |
|---------------|------|------|----------------|
| overArchingTableLayoutPanel | TableLayoutPanel | メインレイアウトパネル（2行構成） | - |
| (動的) | PropPageUserControlBase | ホストされるプロパティページ（行0に配置） | PropPage |
| okCancelTableLayoutPanel | TableLayoutPanel | OK/Cancel ボタン用レイアウト（行1に配置） | - |
| OK | Button | 「OK」ボタン（DialogResult.OK） | - |
| Cancel | Button | 「Cancel」ボタン（DialogResult.Cancel） | - |

## イベント仕様

### 1-PropPage プロパティ Set

プロパティページを設定する際の処理。

1. SuspendLayout でレイアウトを一時停止
2. 以前のページが存在する場合、overArchingTableLayoutPanel から削除
3. 新しいページを m_propPage に設定
4. ダイアログの BackColor をページの BackColor に合わせる
5. ページの PageResizable に応じて FormBorderStyle を設定（Sizable / FixedDialog）
6. ページの Margin, Anchor, TabIndex を設定
7. overArchingTableLayoutPanel の行0に追加
8. ResumeLayout と PerformLayout でレイアウトを再開
9. SetFocusToPage で最初のフォーカス可能なコントロールにフォーカスを設定

### 2-OK_Click

「OK」ボタン押下時の処理。

1. PropPage.IsDirty が True の場合、PropPage.Apply() を呼び出し
2. 変更を保存
3. ダイアログを閉じる
4. ValidationException が発生した場合、ShowErrorMessage でエラーを表示し、RestoreFocus() でフォーカスを復元
5. SystemException / その他の Exception が発生した場合、ShowErrorMessage でエラーを表示

### 3-Cancel_Click

「Cancel」ボタン押下時の処理。

1. PropPage.RestoreInitialValues() を呼び出し、初期値に復元
2. ダイアログを閉じる

### 4-OnFormClosing

フォームクローズ時の処理。

1. CloseReason.None の場合（OK クリックで検証失敗）、e.Cancel = True でクローズをキャンセル
2. DialogResult が OK 以外の場合、PropPage.RestoreInitialValues() で初期値に復元

### 5-OnShown

フォーム表示時の処理。

1. MinimumSize が空の場合、現在の Size を MinimumSize に設定
2. AutoSize を False に設定（これ以降は手動サイズ制御）

### 6-HelpButtonClicked

ヘルプボタン（?）クリック時の処理。

1. e.Cancel = True でデフォルト動作をキャンセル
2. ShowHelp メソッドを呼び出し（BaseDialog から継承）

### 7-F1Keyword プロパティ Get

F1 キーワードを取得する処理。

1. ベースクラスの F1Keyword が設定されている場合はそれを返す
2. そうでなく m_propPage が設定されている場合、IPropertyPageInternal.GetHelpContextF1Keyword() を呼び出し

## データベース更新仕様

### 操作別データベース影響一覧

本ダイアログはデータベースを使用しません。変更の保存はホストされたプロパティページの Apply() メソッドに委譲されます。

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|------|---------|------|
| OK ボタン押下 | ホストされたページ | 委譲 | PropPage.Apply() を呼び出し |
| Cancel ボタン押下 | ホストされたページ | 委譲 | PropPage.RestoreInitialValues() を呼び出し |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| (動的) | エラー | ValidationException のメッセージ | Apply 中に検証エラー発生時 |
| (動的) | エラー | SystemException / Exception のメッセージ | Apply 中に例外発生時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ValidationException | ShowErrorMessage でエラー表示、RestoreFocus() でフォーカス復元、ダイアログを閉じない |
| SystemException | ShowErrorMessage でエラー表示、ダイアログを閉じない |
| その他の Exception | Debug.Fail 出力、RethrowIfUnrecoverable で回復不能なら再スロー、ShowErrorMessage でエラー表示 |

## 備考

- BaseDialog クラスを継承し、Visual Studio 統合のダイアログ機能（ヘルプ、サービスプロバイダー連携など）を利用
- ホストされるページの PageResizable に応じて FormBorderStyle が変化（True: Sizable, False: FixedDialog）
- AutoScale は行わない（ホストされるページが自身でスケーリングを処理）
- ダイアログの Padding は 12px 四方に設定
- MinimumSize は OnShown 時に自動設定され、それ以下へのリサイズは不可
- HelpButton=True, MaximizeBox=False, MinimizeBox=False, ShowIcon=False, ShowInTaskbar=False

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 継承関係を理解する

PropPageHostDialog の継承元と Visual Studio 統合を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | BaseDialog の継承、IServiceProvider の利用 |
| 1-2 | BaseDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/DesignerFramework/BaseDialog.vb` | ShowHelp メソッド、F1Keyword プロパティ |

**読解のコツ**: PropPageHostDialog は BaseDialog を継承し、Visual Studio との統合（ヘルプ、サービスプロバイダー）を行います。

#### Step 2: プロパティページのホスト機能を理解する

PropPage プロパティのセッター処理を追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | PropPage プロパティ Set |

**主要処理フロー**:
1. **行 39-77**: PropPage Set - ページの動的ホスト処理
2. **行 56-60**: FormBorderStyle の動的設定（PageResizable に応じて）
3. **行 68**: overArchingTableLayoutPanel への追加

#### Step 3: OK/Cancel 処理を理解する

ダイアログの確定/キャンセル処理を追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | OK_Click, Cancel_Click, OnFormClosing |

**主要処理フロー**:
- **行 199-220**: OK_Click - IsDirty チェック、Apply() 呼び出し、例外処理
- **行 194-197**: Cancel_Click - RestoreInitialValues() 呼び出し
- **行 222-231**: OnFormClosing - クローズ条件の判定

#### Step 4: ヘルプ機能を理解する

F1 キーワードの取得とヘルプ表示を追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | F1Keyword プロパティ, HelpButtonClicked |

**主要処理フロー**:
- **行 26-37**: F1Keyword プロパティ - ホストされたページから F1 キーワードを取得
- **行 247-250**: HelpButtonClicked - ShowHelp の呼び出し

#### Step 5: フォーカス管理を理解する

初期フォーカスの設定処理を追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | SetFocusToPage メソッド |

**主要処理フロー**:
- **行 233-245**: SetFocusToPage - 最初のフォーカス可能なコントロールにフォーカスを設定

### プログラム呼び出し階層図

```
PropPageUserControlBase (子ページ表示時など)
    │
    └─ PropPageHostDialog
           │
           ├─ New(ServiceProvider, F1Keyword)
           │      └─ InitializeComponent
           │
           ├─ PropPage = <PropPageUserControlBase>
           │      │
           │      ├─ BackColor 設定
           │      ├─ FormBorderStyle 設定 (PageResizable に依存)
           │      ├─ overArchingTableLayoutPanel.Controls.Add
           │      └─ SetFocusToPage
           │
           ├─ ShowDialog
           │      │
           │      │   [OnShown]
           │      │   └─ MinimumSize = Size, AutoSize = False
           │      │
           │      │   [ユーザー操作]
           │      │   │
           │      │   ├─ OK_Click
           │      │   │      ├─ PropPage.IsDirty チェック
           │      │   │      ├─ PropPage.Apply()
           │      │   │      └─ Close (または例外処理)
           │      │   │
           │      │   ├─ Cancel_Click
           │      │   │      ├─ PropPage.RestoreInitialValues()
           │      │   │      └─ Close
           │      │   │
           │      │   └─ HelpButtonClicked
           │      │          └─ ShowHelp (BaseDialog)
           │      │
           │      └─ [OnFormClosing]
           │             ├─ CloseReason.None → Cancel
           │             └─ DialogResult != OK → RestoreInitialValues
           │
           └─ F1Keyword プロパティ
                  └─ IPropertyPageInternal.GetHelpContextF1Keyword()
```

### データフロー図

```
[入力]                         [処理]                          [出力]

PropPageUserControlBase
(呼び出し元)
    │
    ├─ ServiceProvider    ───▶  New(ServiceProvider, F1Keyword)
    ├─ F1Keyword          ───▶  │
    │                           ▼
    └─ PropPage           ───▶  PropPage プロパティ Set
                                │
                                ├─▶ FormBorderStyle 設定
                                ├─▶ overArchingTableLayoutPanel 配置
                                └─▶ SetFocusToPage
                                     │
                                     ▼
                                [ユーザー操作]
                                     │
                                ┌────┴────┐
                                │         │
                                ▼         ▼
                           OK_Click   Cancel_Click
                                │         │
                                ▼         ▼
                           Apply()   RestoreInitialValues()
                                │         │
                                └────┬────┘
                                     │
                                     ▼
                           [ダイアログクローズ]
                                     │
                                     ▼
PropPageUserControlBase  ◀───  DialogResult (OK / Cancel)
(呼び出し元)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PropPageHostDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.vb` | ソース | プロパティページホストダイアログ本体 |
| PropPageHostDialog.resx | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageHostDialog.resx` | リソース | UI 文字列、レイアウト定義 |
| BaseDialog.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/DesignerFramework/BaseDialog.vb` | ソース | ベースダイアログクラス、ShowHelp 提供 |
| PropPageUserControlBase.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageUserControlBase.vb` | ソース | ホストされるページの基底クラス |
| IPropertyPageInternal.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/IPropertyPageInternal.vb` | ソース | GetHelpContextF1Keyword インターフェース |
| ValidationException.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/Common/ValidationException.vb` | ソース | 検証例外、RestoreFocus メソッド |
