# Double Buffer Architecture Research v19
## v6 Phase 1 診斷結果

---

## 排除的假說

| 假說 | 結果 |
|------|------|
| ShowCaret 無限循環（v8） | ❌ 排除 — paint count = 100（正常） |
| font 未 SelectObject | ❌ 排除 — PaintText 正確 SelectObject on g_hPaintDC |
| BeginPaint/EndPaint 衝突 | ❌ 排除 — 與 v4 結構相同 |

## 確認的問題

### 1. PaintText final BitBlt 在 bUseMemDC=2 時仍寫 s_hdcPaintBuf
- **已修正**：改為 `bUseMemDC == 1` 才寫
- **效果**：修正後可以輸入

### 2. 畫面「瞬間正確然後回到登入畫面」
- 輸入正常、程式邏輯正常（進入選單）
- 但畫面沒有持續更新
- **根因推測**：WndProc 的 writeback 只寫 s_rcLastPaint（dirty region），但畫面切換時需要全螢幕更新。非 dirty 區域保留 shared buffer 的舊內容。
- **與 v5 相同的核心矛盾**：持久 buffer 的非 dirty 區域保留舊畫面

## v6 的核心挑戰

### 為什麼 v4 沒問題但 v6 有問題？

```
v4: PaintText 管理 s_hdcPaintBuf（自己的 buffer）
    每次 WM_PAINT：capture screen → buffer → TextOut → skip screen
    ★ capture 確保 buffer 的 dirty 區域有最新螢幕內容
    ★ TextOut 覆蓋 dirty cells
    ★ 結果：buffer = 最新的螢幕 + 新的 TextOut = 正確

v6: WndProc 管理 g_hSharedDC（共用 buffer）
    首次：capture 全螢幕 → buffer
    後續 WM_PAINT：PaintText capture dirty region → buffer → TextOut
    ★ PaintText capture 把螢幕 dirty 區域寫入 buffer ← 跟 v4 一樣
    ★ TextOut 覆蓋 dirty cells ← 跟 v4 一樣
    ★ 結果應該跟 v4 一樣！
```

### 為什麼結果不同？

**可能原因：PaintText 在 v6 中沒有正確 capture。**

讓我重新檢查：v6 的 PaintText code：
```c
if( g_hPaintDC )
{
   BitBlt( g_hPaintDC ← hdcScreen, ps.rcPaint );
   hdc = g_hPaintDC;
   bUseMemDC = 2;
}
```

這裡 `g_hPaintDC` 是 WndProc 的 shared buffer。capture 把 screen 的 dirty 區域寫入 shared buffer。然後 TextOut 用 `hdc = g_hPaintDC` 畫到 shared buffer。

**但 `ps.rcPaint` 可能不正確！**

在 v6 WndProc 中，CallWindowProcW 呼叫 PaintText。PaintText 的 BeginPaint 讀取 update region 並返回 ps.rcPaint。但在 WndProc 呼叫 CallWindowProcW 之前，WndProc 已經用 GetUpdateRect 讀取了 s_rcLastPaint。

**問題：GetUpdateRect 是否消耗了 update region？**

GetUpdateRect(hWnd, &rect, FALSE) — FALSE 表示不清除。所以 update region 保留。BeginPaint 可以正確讀取。

**排除。**

### 下一步

需要在 v6 PaintText 中加 debug：記錄 ps.rcPaint 的大小和 TextOut 的行數。確認是否所有 dirty cell 都被重繪。

## 結論

v6 的「畫面停在登入」問題尚未完全解決。已修正 bUseMemDC 判斷（可輸入了），但畫面更新不持續。需要更多 debug 追蹤 dirty region 的覆蓋範圍。

**v4 full 仍為穩定版。v6 研究繼續。**
