# 画面設計書 66-Screens

## 概要

本ドキュメントは、Avalonia UIフレームワークのControlCatalogサンプルアプリケーションにおけるScreensデモページの画面設計書です。マルチモニター環境でのスクリーン情報取得・表示機能を実証するためのデモ画面を定義します。

### 本画面の処理概要

本画面は、システムに接続されているすべてのモニター（スクリーン）の情報を視覚的に表示するページです。各スクリーンの境界、作業領域、スケーリング、プライマリフラグなどの詳細情報を取得し、視覚的な図とテキスト情報の両方で表示します。コードのみで構成され、XAMLファイルは存在しません。

**業務上の目的・背景**：
マルチモニター環境でのアプリケーション開発では、各スクリーンの特性（解像度、スケーリング、位置関係）を正確に把握することが重要です。ウィンドウの配置、フルスクリーン表示、マルチモニター対応UIなどを実装する際に、Screens APIの理解が不可欠です。本デモページは、AvaloniaのScreens APIの使用方法と取得可能な情報を開発者に示すことを目的としています。

**画面へのアクセス方法**：
ControlCatalogアプリケーションのメインウィンドウから、HamburgerMenuナビゲーションを使用して「Screens」項目を選択することでアクセスします。

**主要な操作・処理内容**：
1. スクリーン詳細リクエスト：「Request ScreenDetails」ボタンでスクリーン情報の詳細取得を要求
2. スクリーンの視覚的表示：各モニターを矩形として描画（スケール1/10）
3. プライマリスクリーン識別：プライマリモニターを青色、その他をグレーで表示
4. アクティブスクリーン表示：現在のウィンドウがあるスクリーンを強調表示
5. 詳細情報表示：DisplayName、Handle、Bounds、WorkArea、Scaling、IsPrimary、CurrentOrientation

**画面遷移**：
- 遷移元：MainView（HamburgerMenuナビゲーション経由）
- 遷移先：なし（デモページのため他画面への遷移機能なし）

**権限による表示制御**：
なし（デモアプリケーションのため権限管理は実装されていません）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 46 | Screens | 主機能 | スクリーン情報表示、マルチモニター環境での画面情報取得 |

## 画面種別

デモ / 情報表示

## URL/ルーティング

ControlCatalogアプリケーション内のHamburgerMenuナビゲーションで「Screens」を選択

## 入出力項目

| 項目名 | 項目種別 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| ScreenDetails | 出力 | IReadOnlyList<Screen> | - | 取得したスクリーン情報一覧 |

## 表示項目

| 項目名 | 表示形式 | データソース | 説明 |
|--------|----------|--------------|------|
| Request ScreenDetailsボタン | Button | - | スクリーン詳細情報の取得リクエスト |
| スクリーン図 | 描画（DrawRectangle） | Screens.All | 各スクリーンを1/10スケールで矩形描画 |
| スクリーン番号 | 描画（DrawText） | インデックス+1 | 各スクリーンの識別番号 |
| ウィンドウ位置 | 描画（DrawRectangle） | Window.Position | 現在のウィンドウ位置を矩形で表示 |
| Screen N タイトル | FormattedText | スクリーンインデックス | 各スクリーンのセクションヘッダー |
| DisplayName | FormattedText | Screen.DisplayName | スクリーンの表示名 |
| Handle | FormattedText | Screen.TryGetPlatformHandle() | プラットフォームハンドル |
| Bounds | FormattedText | Screen.Bounds | スクリーンの境界（幅:高さ） |
| WorkArea | FormattedText | Screen.WorkingArea | 作業領域（幅:高さ） |
| Scaling | FormattedText | Screen.Scaling | スケーリング係数（%表示） |
| IsPrimary | FormattedText | Screen.IsPrimary | プライマリスクリーンフラグ |
| CurrentOrientation | FormattedText | Screen.CurrentOrientation | 現在の画面向き |
| Current | FormattedText | 比較結果 | アクティブスクリーンかどうか |

## イベント仕様

### 1-Request ScreenDetailsボタン押下

スクリーン詳細情報の取得を要求します。

- **トリガー**: ボタンのクリック
- **処理内容**: TopLevel.Screens.RequestScreenDetails()の非同期呼び出し
- **結果表示**: ボタンテキストを"Request ScreenDetails: Granted"または"Denied"に更新

### 2-ウィンドウ位置変更

ウィンドウが移動すると画面を再描画します。

- **トリガー**: Window.PositionChanged
- **処理内容**: InvalidateVisual()を呼び出して再描画

### 3-スクリーン構成変更

モニター構成が変更されると画面を再描画します。

- **トリガー**: Screens.Changed
- **処理内容**: コンソールに"Screens Changed"を出力し、InvalidateVisual()で再描画

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

本画面はデータベースを使用しません。

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

該当なし

## メッセージ仕様

| メッセージID | 種別 | 表示タイミング | メッセージ内容 |
|-------------|------|---------------|---------------|
| M-01 | 情報 | Screens API非対応時 | "Current platform doesn't support Screens API." |
| M-02 | ボタン更新 | RequestScreenDetails成功時 | "Request ScreenDetails: Granted" |
| M-03 | ボタン更新 | RequestScreenDetails失敗時 | "Request ScreenDetails: Denied" |

## 例外処理

| 例外ケース | 対応処理 |
|-----------|---------|
| Screens API非対応プラットフォーム | エラーメッセージを表示 |
| スクリーン情報取得失敗 | ボタンテキストに"Denied"を表示 |

## 備考

- 本ページはXAMLを使用せず、完全にコードで描画を行います
- Renderメソッドをオーバーライドしてカスタム描画を実装
- スクリーンは1/10スケールで描画され、プライマリは青色（#FF0078D7）で表示
- BypassFlowDirectionPolicies = trueで右から左へのレイアウト方向を無視
- FormattedTextを使用して緑色のテキストで情報を描画

---

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

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

### 推奨読解順序

#### Step 1: クラス構造を理解する

コードのみで構成されるこのページの基本構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | UserControl継承、フィールド定義（16-21行目） |

**読解のコツ**: このクラスはXAMLを持たないコードオンリーのUserControlです。コンストラクタでButtonを動的に生成し、Renderメソッドをオーバーライドしてカスタム描画を行います。

#### Step 2: 初期化とイベント登録を理解する

コンストラクタとVisualTree接続時の処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | コンストラクタ（23-36行目）- ボタン生成とクリックハンドラ |
| 2-2 | ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | OnAttachedToVisualTree（40-58行目）- イベント登録 |

**主要処理フロー**:
1. **25-35行目**: Buttonを生成し、クリック時にRequestScreenDetails()を呼び出し
2. **44-48行目**: Window.PositionChangedで再描画
3. **50-57行目**: Screens.Changedで再描画

#### Step 3: 描画処理を理解する

Renderメソッドのカスタム描画ロジックを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | Render（60-161行目）- メイン描画処理 |
| 3-2 | ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | ヘルパーメソッド（163-172行目）- FormattedText生成 |

**主要処理フロー**:
- **66-71行目**: Screens API非対応時のエラー表示
- **76-108行目**: 各スクリーンを矩形として描画
- **110-151行目**: 各スクリーンの詳細情報をテキストで描画
- **153-160行目**: ウィンドウ位置を矩形で描画

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

```
ScreenPage (UserControl)
    │
    ├─ コンストラクタ
    │      └─ Button生成
    │             └─ Click → RequestScreenDetails()
    │
    ├─ OnAttachedToVisualTree()
    │      ├─ Window.PositionChanged → InvalidateVisual()
    │      └─ Screens.Changed → InvalidateVisual()
    │
    └─ Render(DrawingContext)
           │
           ├─ Screens API非対応チェック
           │      └─ DrawText("Current platform doesn't support...")
           │
           ├─ ScreenからActiveScreenを取得
           │      └─ ScreenFromTopLevel(topLevel)
           │
           ├─ 各スクリーンの矩形描画
           │      ├─ DrawRectangle (Bounds)
           │      ├─ DrawRectangle (WorkingArea)
           │      └─ DrawText (スクリーン番号)
           │
           ├─ 各スクリーンの詳細情報描画
           │      ├─ CreateFormattedText("Screen N")
           │      ├─ CreateFormattedText("DisplayName: ...")
           │      ├─ CreateFormattedText("Handle: ...")
           │      ├─ CreateFormattedText("Bounds: ...")
           │      ├─ CreateFormattedText("WorkArea: ...")
           │      ├─ CreateFormattedText("Scaling: ...")
           │      ├─ CreateFormattedText("IsPrimary: ...")
           │      ├─ CreateFormattedText("CurrentOrientation: ...")
           │      └─ CreateFormattedText("Current: ...")
           │
           └─ ウィンドウ位置の矩形描画
                  └─ DrawRectangle (Window位置)
```

### データフロー図

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

Button.Click ─────────────────▶ RequestScreenDetails() ───────────▶ ボタンテキスト更新
                                       │
                                       ▼
TopLevel.Screens ─────────────────────▶ Screens.All ──────────────▶ スクリーン情報取得
     │                                       │
     ├─ Screens.Changed ──────────────▶ InvalidateVisual() ───────▶ 再描画
     │                                       │
     └─ ScreenFromTopLevel() ─────────▶ activeScreen ─────────────▶ アクティブスクリーン判定

Window.Position ──────────────▶ PositionChanged ─────────────────▶ InvalidateVisual()
                                                                         │
                                                                         ▼
DrawingContext ◀─────────────────────────────────────────────────── Render()
     │
     ├─ DrawRectangle ────────────────────────────────────────────▶ スクリーン図
     ├─ DrawText ─────────────────────────────────────────────────▶ スクリーン番号
     └─ CreateFormattedText ──────────────────────────────────────▶ 詳細情報テキスト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ScreenPage.cs | `samples/ControlCatalog/Pages/ScreenPage.cs` | ソース | 画面全体の実装（XAMLなし） |
| Screens.cs | `src/Avalonia.Controls/Platform/Screens.cs` | ソース | Screens API実装 |
| Screen.cs | `src/Avalonia.Controls/Platform/Screen.cs` | ソース | Screenクラス定義 |
| DrawingContext.cs | `src/Avalonia.Base/Media/DrawingContext.cs` | ソース | 描画コンテキスト |
| FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | ソース | 書式付きテキスト |
