# 機能設計書 125-クリップボード操作

## 概要

本ドキュメントは、KShootManiaにおけるWin32クリップボードの読み書き機能の設計を記述する。テキスト・ビットマップ・ファイルリストの各形式でクリップボードとのデータ交換を行う。

### 本機能の処理概要

本機能は、Win32 APIのクリップボード関連関数をHSP3モジュールとしてラップし、テキスト・ビットマップ・ファイルリストの3形式でクリップボードとのデータ交換を提供する。リザルト画面でのスクリーンショットコピー、選曲画面での譜面パスコピーなどで使用される。

**業務上の目的・背景**：ゲームのリザルト画面でスクリーンショットをクリップボードにコピーしてSNS等に共有する機能、選曲画面で譜面ファイルのパスをクリップボードにコピーして外部エディタで開く機能など、Windowsのクリップボード連携が必要な場面がある。

**機能の利用シーン**：
- リザルト画面・コースリザルト画面でのスクリーンショットコピー（ClipB_SetBmp）
- 選曲画面でのCtrl+Cによる譜面パスコピー（HSP3標準のclipset命令を使用）
- 選曲画面でのCtrl+Vによるクリップボードテキスト取得の可能性

**主要な処理内容**：
1. ClipB_GetText: クリップボードからテキスト文字列を取得
2. ClipB_SetText: クリップボードにテキスト文字列を設定
3. ClipB_GetBmpSize: クリップボード内のビットマップサイズを取得
4. ClipB_GetBmp: クリップボードのビットマップをウィンドウにコピー
5. ClipB_SetBmp: ウィンドウの画像をクリップボードにコピー
6. ClipB_GetFile: クリップボードからファイルリストを取得
7. ClipB_SetFile: クリップボードにファイルリストを設定
8. ClipB_GetFileMode: クリップボードのファイル操作モード取得
9. ClipB_SetEmpty: クリップボードを空にする

**関連システム・外部連携**：Win32 API (user32.dll, kernel32.dll, gdi32.dll, shell32.dll) を使用。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 参照画面 | Ctrl+Cによる譜面パスのクリップボードコピー |
| 6 | リザルト画面 | 主機能 | スクリーンショットのクリップボードコピー(ClipB_SetBmp) |
| 7 | コースリザルト画面 | 主機能 | スクリーンショットのクリップボードコピー(ClipB_SetBmp) |

## 機能種別

データ連携（Win32クリップボード操作）

## 入力仕様

### 入力パラメータ

#### ClipB_SetText

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| s | str | Yes | クリップボードに設定するテキスト文字列 | なし |

#### ClipB_SetBmp

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | int | Yes | コピー元の左上X座標 | 0以上 |
| y | int | Yes | コピー元の左上Y座標 | 0以上 |
| w | int | Yes | コピーする幅(ピクセル) | 1以上 |
| h | int | Yes | コピーする高さ(ピクセル) | 1以上 |

#### ClipB_GetText

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| t | var | Yes | 取得したテキストを格納する変数 | なし |

### 入力データソース

Windowsクリップボード、またはプログラム内の変数・画面バッファ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| テキスト (GetText) | str | クリップボードのテキスト文字列 |
| stat (SetText) | int | 1=成功、0=失敗 |
| stat (GetBmp) | int | 1=成功、0=失敗 |
| ファイルリスト (GetFile) | str | 改行区切りのファイルパス一覧 |
| stat (GetFile) | int | 取得したファイル数(0=失敗) |
| ファイルモード (GetFileMode) | int | 0:なし, +1:コピー, +2:切り取り, +4:リンク |

### 出力先

呼び出し元モジュールの変数、またはWindowsクリップボード

## 処理フロー

### 処理シーケンス

```
1. ClipB_SetBmp (スクリーンショットコピー)
   ├─ GetDC: デスクトップDCを取得
   ├─ CreateCompatibleDC: 互換DC作成
   ├─ CreateCompatibleBitmap: 互換ビットマップ作成
   ├─ BitBlt: HSPウィンドウからビットマップにコピー
   ├─ OpenClipboard: クリップボードを開く
   ├─ EmptyClipboard: クリップボードをクリア
   ├─ SetClipboardData(CF_BITMAP): ビットマップを設定
   └─ CloseClipboard: クリップボードを閉じる

2. ClipB_SetText (テキスト設定)
   ├─ GlobalAlloc: グローバルメモリ確保
   ├─ GlobalLock: メモリロック
   ├─ 文字列をメモリにコピー
   ├─ GlobalUnlock: メモリアンロック
   ├─ OpenClipboard: クリップボードを開く
   ├─ EmptyClipboard: クリップボードをクリア
   ├─ SetClipboardData(CF_TEXT): テキストを設定
   └─ CloseClipboard: クリップボードを閉じる
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|SetBmp| C[GetDC: デスクトップDC取得]
    C --> D[CreateCompatibleBitmap]
    D --> E[BitBlt: 画面→ビットマップコピー]
    E --> F[OpenClipboard]
    F --> G[EmptyClipboard]
    G --> H[SetClipboardData CF_BITMAP]
    H --> I[CloseClipboard]
    B -->|SetText| J[GlobalAlloc: メモリ確保]
    J --> K[文字列をメモリにコピー]
    K --> L[OpenClipboard]
    L --> M[EmptyClipboard]
    M --> N[SetClipboardData CF_TEXT]
    N --> O[CloseClipboard]
    I --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-125-01 | クリップボード排他制御 | OpenClipboard→操作→CloseClipboardの排他パターンで操作 | 全操作 |
| BR-125-02 | メモリ管理 | SetClipboardData成功時はクリップボード側がメモリ管理、失敗時はGlobalFreeで自前解放 | SetText/SetFile |
| BR-125-03 | データ形式 | CF_TEXT(1)/CF_BITMAP(2)/CF_HDROP(15)の3形式に対応 | 各操作に応じて |
| BR-125-04 | グローバルメモリ | GMEM_ZEROINIT + GMEM_SHAREフラグでメモリ確保 | SetText/SetFile |

### 計算ロジック

特になし。

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| stat=0 | クリップボード開放失敗 | 他アプリがクリップボードを占有 | stat=0を返却し呼び出し元で判定 |
| stat=0 | メモリ確保失敗 | システムメモリ不足 | stat=0を返却 |
| stat=0 | ビットマップなし | クリップボードにビットマップ形式データがない | stat=0を返却 |

### リトライ仕様

リトライ処理なし。

## トランザクション仕様

該当なし。ただし、OpenClipboard/CloseClipboardによる排他制御がトランザクション的な役割を果たす。

## パフォーマンス要件

Win32 APIの直接呼び出しのため、高速に動作する。ビットマップコピー時は画面サイズに比例した処理時間がかかる。

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

- クリップボードは他アプリケーションと共有されるため、機密データの長時間放置は避けるべき
- GlobalAllocで確保したメモリはGMEM_SHAREフラグにより他プロセスからもアクセス可能

## 備考

- 著者: 近藤和 (2005-2011)
- HSP 3.22以降対応
- ClipB_SetFile内でGetFullPathNameによる相対→絶対パス変換を行っている
- kshootmania.hsp 177行目で `#include "third_party/clipboard.as"` としてインクルードされている

---

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

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

### 推奨読解順序

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

Win32 APIの定数とDLL関数宣言を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | clipboard.as | `third_party/clipboard.as` | Win32 API関数宣言(71-118行目): kernel32, user32, gdi32, shell32 |
| 1-2 | clipboard.as | `third_party/clipboard.as` | クリップボード形式定数(93-95行目): CF_TEXT=1, CF_BITMAP=2, CF_HDROP=15 |

**読解のコツ**: HSP3の`#uselib`でDLLを読み込み、`#func`/`#cfunc`で関数をバインドする。`GMEM_ZEROINIT|GMEM_SHARE`はクリップボード連携で必須のメモリ確保フラグ。

#### Step 2: テキスト操作を理解する

最もシンプルなテキスト操作から理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | clipboard.as | `third_party/clipboard.as` | ClipB_GetText(120-133行目): テキスト取得 |
| 2-2 | clipboard.as | `third_party/clipboard.as` | ClipB_SetText(135-150行目): テキスト設定 |

**主要処理フロー**:
1. **122行目**: `IsClipboardFormatAvailable CF_TEXT` - テキスト形式のデータがあるか確認
2. **123行目**: `OpenClipboard hwnd` - クリップボードを開く
3. **125行目**: `GetClipboardData CF_TEXT` - グローバルメモリハンドル取得
4. **127行目**: `GlobalLock ib` - メモリをロック
5. **128行目**: `dupptr dp, ib(2), ib(1), 2` - HSP変数にマッピング
6. **129行目**: `t = dp` - テキストをコピー
7. **130-131行目**: アンロック→クローズ

#### Step 3: ビットマップ操作を理解する

リザルト画面のスクリーンショットで使用されるClipB_SetBmpを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | clipboard.as | `third_party/clipboard.as` | ClipB_SetBmp(185-203行目): ビットマップ設定 |
| 3-2 | result.hsp | `src/scene/result.hsp` | ClipB_SetBmp呼び出し(834行目) |
| 3-3 | course_result.hsp | `src/scene/course_result.hsp` | ClipB_SetBmp呼び出し(618行目) |

**主要処理フロー**:
- **187行目**: `GetDC` - デスクトップDC取得
- **188行目**: `CreateCompatibleDC` - 互換DC作成
- **189行目**: `CreateCompatibleBitmap` - ビットマップ作成
- **192行目**: `BitBlt` - HSPウィンドウ→ビットマップにコピー
- **198-200行目**: OpenClipboard→EmptyClipboard→SetClipboardData

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

```
kshootmania.hsp (177行目: #include)
    |
    +-- result.hsp (834行目)
    |       |
    |       +-- ClipB_SetBmp (clipboard.as:185)
    |               +-- GetDC (user32.dll)
    |               +-- CreateCompatibleDC (gdi32.dll)
    |               +-- CreateCompatibleBitmap (gdi32.dll)
    |               +-- BitBlt (gdi32.dll)
    |               +-- OpenClipboard (user32.dll)
    |               +-- SetClipboardData (user32.dll)
    |               +-- CloseClipboard (user32.dll)
    |
    +-- course_result.hsp (618行目)
    |       |
    |       +-- ClipB_SetBmp (同上)
    |
    +-- select.hsp (273行目)
            |
            +-- clipset (HSP標準命令: テキストコピー)
```

### データフロー図

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

HSPウィンドウ画面 -------> ClipB_SetBmp -----------------> Windowsクリップボード
  (x,y,w,h)                  |                              (CF_BITMAP)
                             +-- BitBlt(画面コピー)
                             +-- SetClipboardData

テキスト文字列 -----------> ClipB_SetText ----------------> Windowsクリップボード
                             |                              (CF_TEXT)
                             +-- GlobalAlloc(メモリ確保)
                             +-- SetClipboardData

Windowsクリップボード ----> ClipB_GetText ----------------> テキスト変数(t)
  (CF_TEXT)                  |
                             +-- GetClipboardData
                             +-- GlobalLock(メモリ読み取り)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| clipboard.as | `third_party/clipboard.as` | ソース | クリップボード操作モジュール本体 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | clipboard.asのインクルード元(177行目) |
| result.hsp | `src/scene/result.hsp` | ソース | ClipB_SetBmp呼び出し元(834行目) |
| course_result.hsp | `src/scene/course_result.hsp` | ソース | ClipB_SetBmp呼び出し元(618行目) |
| select.hsp | `src/scene/select.hsp` | ソース | clipset(HSP標準)によるテキストコピー(273行目) |
