# 通知設計書 2-MsgError

## 概要

本ドキュメントは、StaxRipアプリケーションにおけるエラーメッセージ通知「MsgError」の設計仕様を定義する。MsgErrorは、アプリケーション内で発生したエラーをユーザーに伝達するためのタスクダイアログベースの通知機能であり、コピーボタンとタイムアウト機能を備えている。

### 本通知の処理概要

MsgError通知は、アプリケーションで発生したエラーをユーザーに明確に伝達するための重要な通知メカニズムである。

**業務上の目的・背景**：処理失敗、設定エラー、ファイル操作の失敗などの異常事態をユーザーに即座に通知し、問題の認識と適切な対応を促すために必要である。エラーの内容をクリップボードにコピーできる機能により、サポート問い合わせやログ記録を容易にする。タイムアウト機能により、バッチ処理中のエラー通知が自動的に閉じることも可能。

**通知の送信タイミング**：エラーが検出された瞬間に同期的に表示される。具体的には、MsgError関数が呼び出された時点で即座にタスクダイアログが表示される。タイムアウトが設定されている場合は、指定時間後に自動的に閉じる。

**通知の受信者**：現在アプリケーションを操作しているユーザー。ownerパラメータで指定されたウィンドウハンドルを親とするモーダルダイアログとして表示される。

**通知内容の概要**：エラータイトルとオプションのエラー詳細（content）で構成される。Errorアイコン（赤い×マーク）が表示され、OKボタンと「Copy Message」リンクボタンが配置される。

**期待されるアクション**：ユーザーはエラー内容を確認し、必要に応じてメッセージをクリップボードにコピーする。その後、OKボタンをクリックしてダイアログを閉じ、エラーの原因に対処する。

## 通知種別

アプリ内通知（タスクダイアログ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無し |

### 送信先決定ロジック

handleパラメータで指定されたウィンドウをオーナーとして表示。指定がない場合（IntPtr.Zero）は、GetHandle()メソッドでフォアグラウンドウィンドウを取得して親ウィンドウとする。

## 通知テンプレート

### メール通知の場合

該当なし（アプリ内通知のため）

### 本文テンプレート

```
[タイトル]
{title パラメータの値}

[コンテンツ]（オプション）
{content パラメータの値}

[アイコン]
Error（赤い×アイコン）

[ボタン]
OK

[リンクボタン]
Copy Message（クリックでメッセージをクリップボードにコピー）
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | エラーのタイトルテキスト | 呼び出し元から渡されるString型 | Yes |
| content | エラーの詳細テキスト | 呼び出し元から渡されるString型 | No |
| handle | 親ウィンドウのハンドル | 呼び出し元から渡されるIntPtr型 | No |
| timeout | 自動クローズまでの秒数 | 呼び出し元から渡されるInteger型 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | MsgError関数の呼び出し | timeoutが0以上 | コード内でMsgError()が呼び出された時点で表示 |
| 画面操作 | ダウンロード失敗 | ダウンロード失敗時 | StaxRipUpdate.OnDownloadCompleteで"Download failed!"を表示 |
| 画面操作 | ファイル不在エラー | ダウンロードファイル不在時 | ToolUpdate.Downloadで"Downloaded file is missing."を表示 |
| 画面操作 | 抽出失敗 | 7z抽出失敗時 | ToolUpdate.Extractで"Extraction failed with error exit code X"を表示 |
| 画面操作 | 抽出後ファイル不在 | 抽出後にファイルが見つからない場合 | ToolUpdate.Extractで"File missing after extraction."を表示 |
| 画面操作 | パラメータ不一致 | コマンドパラメータ不一致時 | CommandManager.Processで"Parameter mismatch..."を表示 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| timeout < 0 | timeoutパラメータが負の値の場合は表示されない |
| title = "" かつ content = "" | titleとcontentの両方が空の場合は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[MsgError呼び出し] --> B{timeout < 0?}
    B -->|Yes| C[処理終了]
    B -->|No| D{title = ""?}
    D -->|Yes| E[title = content]
    D -->|No| F[そのまま使用]
    E --> G{title = ""?}
    F --> G
    G -->|Yes| C
    G -->|No| H[TaskDialogインスタンス生成]
    H --> I[Title/Content設定]
    I --> J[Owner設定]
    J --> K[Icon = TaskIcon.Error設定]
    K --> L[ShowCopyButton = True設定]
    L --> M[Timeout設定]
    M --> N[AddButton"OK"設定]
    N --> O[Show呼び出し]
    O --> P[ダイアログ表示]
    P --> Q{タイムアウト?}
    Q -->|Yes| R[自動クローズ]
    Q -->|No| S{ユーザー操作}
    S -->|OK| T[ダイアログクローズ]
    S -->|Copy Message| U[クリップボードコピー]
    U --> S
    R --> V[終了]
    T --> V
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（MsgErrorはデータベースを参照しない）

### テーブル別参照項目詳細

該当なし

### 更新テーブル一覧

該当なし

#### 送信ログテーブル

該当なし（MsgErrorは送信ログを記録しない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| クリップボードコピー失敗 | Clipboard.SetText失敗 | 例外を無視（STAスレッドで実行） |
| ウィンドウハンドル取得失敗 | GetHandle()で取得できない場合 | IntPtr.Zeroを返し、スクリーン中央に表示 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（アプリケーション動作中は常に表示可能）

## セキュリティ考慮事項

- エラーメッセージに詳細なスタックトレースや内部パス情報が含まれる可能性があるため、ユーザーが外部にコピーする際は注意が必要
- クリップボードへのコピー機能はSTAスレッドで実行され、スレッド安全性が確保されている

## 備考

- MsgErrorはMainModuleに定義されたグローバル関数であり、複数のオーバーロードが存在する
- タイムアウト機能は、バッチ処理やバックグラウンド処理中のエラー通知に有用
- ShowCopyButton = Trueにより、blCopyMessageリンクボタンが表示される

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

MsgErrorで使用されるTaskDialogクラスのプロパティと、タイムアウト/コピーボタン機能の構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TaskDialog.vb | `Source/UI/TaskDialog.vb` | Timeoutプロパティ（行16）、ShowCopyButtonプロパティ（行454-466）を確認 |

**読解のコツ**: ShowCopyButtonはWriteOnlyプロパティで、Trueを設定するとblCopyMessageリンクボタンを表示する。

#### Step 2: エントリーポイントを理解する

MsgError関数の複数のオーバーロードと、パラメータ処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | General.vb | `Source/General/General.vb` | MsgError関数の定義（行1222-1240）、2つのオーバーロードの違いを確認 |

**主要処理フロー**:
1. **行1222-1224**: 最初のオーバーロード - handle不要版
2. **行1226-1240**: メインの実装 - timeout/handle対応版
3. **行1227**: timeout < 0で早期リターン
4. **行1228-1229**: titleが空の場合のフォールバック処理
5. **行1231-1240**: TaskDialogの生成と設定

#### Step 3: タイムアウト処理を理解する

TaskDialogのタイムアウト機能の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TaskDialog.vb | `Source/UI/TaskDialog.vb` | Init()メソッド内のTimeout処理（行183-232） |

**主要処理フロー**:
- **行183**: Timeout > 0の条件チェック
- **行186**: TimeoutButton取得（指定されていればそれを、なければAcceptButtonを使用）
- **行194-231**: バックグラウンドタスクでカウントダウン実行
- **行205-209**: ボタンテキストに残り秒数を表示
- **行224-228**: タイムアウト時に自動的にダイアログをクローズ

#### Step 4: コピーボタン機能を理解する

ShowCopyButtonプロパティとクリップボード操作の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TaskDialog.vb | `Source/UI/TaskDialog.vb` | ShowCopyButton WriteOnlyプロパティ（行454-466）、GetText()メソッド（行479-491） |

**主要処理フロー**:
- **行454-466**: blCopyMessageの表示設定とクリックハンドラー
- **行460-463**: STAタスクでClipboard.SetText実行後、MsgInfoで完了通知
- **行479-491**: GetText()でTitle、Content、ExpandedContentを結合してコピー対象テキストを生成

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

```
MsgError(title, content, timeout)  [General.vb:1222]
    |
    +-- MsgError(title, content, IntPtr.Zero, timeout)  [General.vb:1226]
           |
           +-- New TaskDialog(Of String)()  [TaskDialog.vb:8]
           |
           +-- TaskDialog.Title = title
           +-- TaskDialog.Content = content
           +-- TaskDialog.Owner = handle
           +-- TaskDialog.Icon = TaskIcon.Error
           +-- TaskDialog.ShowCopyButton = True
           +-- TaskDialog.Timeout = timeout
           +-- TaskDialog.AddButton("OK")
           |
           +-- TaskDialog.Show()  [TaskDialog.vb:552]
                  |
                  +-- TaskDialog.Init()  [TaskDialog.vb:43]
                  |      |
                  |      +-- StockIcon.GetImage(Error)  [TaskDialog.vb:85]
                  |      |
                  |      +-- Timeout処理開始  [TaskDialog.vb:183]
                  |             |
                  |             +-- g.RunTask() バックグラウンドカウントダウン
                  |
                  +-- ShowDialog()  [TaskDialog.vb:557]
```

### データフロー図

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

title (String) ────> フォールバック判定 ───> TaskDialog.Title設定
                          |
content (String) ──> 空チェック ───────────> TaskDialog.Content設定
                          |
handle (IntPtr) ───> Owner設定 ────────────> ウィンドウ親子関係
                          |
timeout (Integer) ─> Timeout設定 ──────────> カウントダウン開始
                          |
TaskIcon.Error ────> Icon設定 ─────────────> pbIcon.Image設定
                          |
ShowCopyButton=True > blCopyMessage表示 ───> [Copy Message]ボタン
                          |
                    ShowDialog() ─────────> [画面表示]
                          |
               ┌─────────┴─────────┐
               ↓                    ↓
        [タイムアウト]        [ユーザー操作]
               ↓                    ↓
        自動クローズ         OK/Copyクリック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| General.vb | `Source/General/General.vb` | ソース | MsgError関数の定義（MainModule内） |
| TaskDialog.vb | `Source/UI/TaskDialog.vb` | ソース | TaskDialog(Of T)クラス、タイムアウト/コピー機能の実装 |
| TaskDialogBaseForm.vb | `Source/UI/TaskDialogBaseForm.vb` | ソース | blCopyMessageコントロールの定義 |
| StockIcon.vb | `Source/UI/StockIcon.vb` | ソース | Errorアイコン取得ユーティリティ |
| StaxRipUpdate.vb | `Source/General/StaxRipUpdate.vb` | ソース | MsgErrorの使用例（ダウンロード失敗） |
| ToolUpdate.vb | `Source/General/ToolUpdate.vb` | ソース | MsgErrorの使用例（抽出失敗、ファイル不在） |
| GlobalClass.vb | `Source/General/GlobalClass.vb` | ソース | g.RunSTATaskの定義（クリップボード操作用） |
