UI 重构:文档更新为 P0-P3 + P5(1)(共享表面与退出崩溃修复)
- Documents/UI_Refactor_Progress.md:阶段看板标记 P5 部分完成;新增第 5 条提交记录 (UiSurface / top-down DIB / Shutdown 顺序修复 / Render 保护 / 69 项断言 / 8 场景哈希); 修正重复标题;「下一步」重写为 TabBar→菜单→面板→脏区并集。 - Documents/UI_Refactor_Report.md:标题与交付表纳入 P5(1);关键数字更新(69 项断言、 产物 883,200 B、共享 DIB);新增第 7 节描述共享表面与退出期崩溃修复;后续章节重编号。 验证:make release / make debug 零警告;Tools/uicheck 69/69;8 场景渲染哈希与改造前一致。
This commit is contained in:
1 parent
b60debc4ee
commit
4f3c88f398
2 files changed
+68
-15
No files matched your search
@@ -20,7 +20,7 @@
|
||||
| **P2** | `PlotViewPaint.cpp` 零行为分片 | ✅ 完成(**逐像素 0 差异**,见 §2/§3) |
|
||||
| **P3** | 迁移 chrome(Toolbar / TabBar / 菜单 / 拾色器 / 列表行) | 🔄 **Toolbar 已完成**,其余待做 |
|
||||
| **P4** | 迁移 5 个浮动面板 | ⏳ 待做 |
|
||||
| **P5** | 波形管线包成叶子 surface + 共享 DIB | ⏳ 待做 |
|
||||
| **P5** | 波形管线包成叶子 surface + 共享 DIB | 🔄 **UiSurface + DIB 已完成**;脏区并集待做 |
|
||||
|
||||
---
|
||||
|
||||
@@ -175,13 +175,48 @@ Tools/uicheck/uicheck.exe # 62 passed, 0 failed
|
||||
|
||||
---
|
||||
|
||||
### 5. `P5(1)`:共享表面 `UiSurface` + 后备缓冲改 top-down 32bpp DIB(**逐像素 0 差异**)
|
||||
|
||||
**新增** `Components/Shared/{Inc,Src}/UiSurface.*`:`{ dc, rect, stride, bits, version, scale }`。
|
||||
`SubView(localRect)` 把子矩形换算到宿主坐标、**夹取**在本表面内、按 `stride` 重算 `bits` 偏移、传递 `version`。
|
||||
|
||||
> ⚠️ 文件头注释里明确写了取舍:**画控件只需要 `dc + rect`**;`bits` 只在 CPU 侧合成
|
||||
> (memcpy / alpha 混合 / 重采样)时才有意义。用 `bits` 直写像素来"画"控件会破坏 ClearType、
|
||||
> 引入 stride / 翻转 / 写序三类错,是净亏损。
|
||||
|
||||
**`Application`**:
|
||||
* 后备缓冲由 `CreateCompatibleBitmap` 改为 **top-down 32bpp `CreateDIBSection`**
|
||||
(`biHeight` 取负 ⇒ `bits` 从第一行开始、y 向下递增);
|
||||
* 新增 `m_backBits` / `m_backStride` / `m_backVersion`,重建位图时 `++m_backVersion`;
|
||||
* 新增 `BackBufferSurface()` 对外暴露整块表面。
|
||||
|
||||
**顺带修掉一个真实缺陷(退出期访问违例)**:
|
||||
|
||||
| 问题 | 修法 |
|
||||
| --- | --- |
|
||||
| `Shutdown()` 里先 `GdiplusShutdown` 再 `DestroyWindow`:`DestroyWindow` 期间派发的 `WM_PAINT` 会进 `Render()`,在**已关闭**的 GDI+ 上构造 `Graphics` ⇒ 崩溃 | 顺序改为 **先销毁窗口 / 注销类,最后 shutdown GDI+** |
|
||||
| 任何晚到的绘制都可能踩到这条路径 | `Render()` 开头加保护:`!m_gdiplusReady || m_hwnd == nullptr` 直接返回 |
|
||||
|
||||
> 另:临时探针此前的退出崩溃其实来自"探针自己又调了一次 `GdiplusShutdown`"(`Application::Shutdown`
|
||||
> 内部已 shutdown)——与本轮修复无关,但顺序调整与 `Render` 保护保留为防御性正确做法。
|
||||
|
||||
**验证**
|
||||
|
||||
1. 8 场景像素哈希与 DIB 改造前**逐一相同**;3 条工具栏功能断言仍 PASS。
|
||||
2. `Tools/uicheck` **69/69**(新增 7 条 `UiSurface` 断言:bits 按 stride 偏移、矩形夹取、
|
||||
完全在外返回无效表面、`version`/`scale` 传递)。
|
||||
3. `make release` / `make debug` 零警告;`Target.exe` **883 200 B**(< 900 KB)。
|
||||
|
||||
---
|
||||
|
||||
## 下一步(接手者请从这里开始)
|
||||
|
||||
1. **P3 续**:按同一套路迁移 `TabBar`(标签 + 「+」按钮 + 重命名内联输入框)→ 再迁移
|
||||
`PopupMenu` / `ColorPickerPopup` 的条目行。判据同为"8+ 场景像素哈希一致 + 功能断言"。
|
||||
1. **P3 续**:`TabBar`(标签 + 「+」+ 重命名内联 + 拖拽排序)→ `PopupMenu` / `ColorPicker` 条目行。
|
||||
建议把"标签"做成 `UiButtonWidget` 的派生(含 ✕ 热区与拖拽),`TabBar` 只保留重命名编辑与排序语义。
|
||||
2. **P4**:5 个浮动面板(`EdgePanelLayoutFor` 651 行 → 真控件;Stack + Abs + Measure-driven),
|
||||
消掉 `rowRefs/rowChecks/rowPoints/rowOrder/rowLevelTracks/...` 等平行数组。
|
||||
⚠️ 每个面板单独一轮;吸顶/滚动/滚动条/滑块复位/行悬停压暗/开关联动是 6 轮补丁叠出的隐式约定。
|
||||
3. **P5**:共享 top-down 32bpp `CreateDIBSection` + `SurfaceView{dc,rect,stride,bits,version}`,
|
||||
把 56 处 `InvalidateRect` 收敛成脏区并集。
|
||||
4. 每阶段单独提交,提交信息写清"改了什么 / 为什么 / 怎么验证"。
|
||||
消掉 `rowRefs/rowChecks/rowPoints/rowOrder/rowLevelTracks/...` 平行数组。
|
||||
⚠️ 每个面板单独一轮;吸顶 / 滚动 / 滚动条 / 滑块复位 / 行悬停压暗 / 开关联动是 6 轮补丁叠出的隐式约定。
|
||||
3. **P5(2)**:把 56 处 `InvalidateRect` 收敛为 `Host::Invalidate(rect)` 的区域并集,
|
||||
并把 `UiWidget` 的脏区树接到 `Application::Render`(一次回送)。
|
||||
⚠️ 回送仍必须**有无条件 `else`**(历史:某分支缺兜底 ⇒ 一个像素都没回送)。
|
||||
4. 每阶段单独提交,判据固定为:`uicheck` 全绿 + **8+ 场景像素哈希一致** + **功能断言**。
|
||||
@@ -1,4 +1,4 @@
|
||||
# UI 重构报告(P0 / P1 / P2 / P3-Toolbar)
|
||||
# UI 重构报告(P0 / P1 / P2 / P3-Toolbar / P5-共享表面)
|
||||
|
||||
日期:2026-10-28 分支:`UI_Refactor`(从 `dev` 切出;`dev` 又由 `main@df715a0` 切出)
|
||||
所有提交**只在本地仓库**,`main` / `dev` 未受影响。计划见 `UI_Refactor_Plan.md`,台账见 `UI_Refactor_Progress.md`。
|
||||
@@ -13,10 +13,13 @@
|
||||
| **P1** | UI 基础层 `Components/Shared/{Inc,Src}/UiLayout.*` + `UiWidget.*`(约 1 440 行含注释) | ✅ |
|
||||
| **P2** | `PlotView` 实现按关注点重分为**七个分片**;`PlotViewPaint.cpp` 9 080 → **4 913** 行(**−46%**) | ✅ |
|
||||
| **P3** | **Toolbar 已迁移到控件树**(新增 `UiButtonWidget`,公开 API 未变、逐像素 0 差异) | ✅(1/5 组件) |
|
||||
| **P5(1)** | **共享表面 `UiSurface`** + 后备缓冲改 **top-down 32bpp DIB**;顺带修复退出期崩溃 | ✅ |
|
||||
|
||||
五个提交:
|
||||
六个提交:
|
||||
|
||||
```
|
||||
955666b UI 重构 P5(1):共享表面 UiSurface + 后备缓冲改 top-down 32bpp DIB;修复退出期绘制崩溃
|
||||
e14caec UI 重构:报告更新为 P0-P3(含 Toolbar 迁移),并补记框架裁剪约定变更
|
||||
84a349f UI 重构 P3:Toolbar 迁移到控件树(新增 UiButtonWidget,逐像素 0 差异 + 功能断言)
|
||||
eb11e63 UI 重构:补充进度台账、阶段报告与共享记忆同步
|
||||
ec3f93f UI 重构 P2 续:把布局与命中几何从绘制分片拆出(PlotViewPanels.cpp,逐像素 0 差异)
|
||||
@@ -33,9 +36,10 @@ b532046 UI 重构 P2:PlotViewPaint.cpp 按关注点分片(机械搬移,
|
||||
| `PlotViewPaint.cpp` | 9 080 行 | **4 913 行(−46%)** |
|
||||
| 最大源文件 | 9 080(`PlotViewPaint.cpp`) | 4 913(`PlotViewPaint.cpp`) |
|
||||
| `PlotView` 实现文件数 | 4 | **7**(职责单一) |
|
||||
| 自动化 UI 探针 | **0** | **62 项断言**(入库、可复跑) |
|
||||
| 自动化 UI 探针 | **0** | **69 项断言**(入库、可复跑) |
|
||||
| 已迁移到控件树的组件 | 0 | **Toolbar**(1 个,含 8 场景像素 A/B + 3 条功能断言) |
|
||||
| 产物 | 873 984 B | **881 664 B**(+7.7 KB,< 900 KB 阈值) |
|
||||
| 共享后台位图 | compatible bitmap(无像素指针) | **top-down 32bpp DIB** + `UiSurface{dc,rect,stride,bits,version}` |
|
||||
| 产物 | 873 984 B | **883 200 B**(+9.2 KB,< 900 KB 阈值) |
|
||||
| 产品像素差异 | — | **0**(分片三场景 + 迁移八场景哈希逐一相同) |
|
||||
|
||||
---
|
||||
@@ -174,7 +178,21 @@ flowchart TD
|
||||
|
||||
---
|
||||
|
||||
## 7. 明确未做的事(避免误解)
|
||||
## 7. P5(1):共享表面与 top-down DIB
|
||||
|
||||
* 新增 `Components/Shared/{Inc,Src}/UiSurface.*`:`{ dc, rect, stride, bits, version, scale }`;
|
||||
`SubView()` 换算子矩形、**夹取**在本表面内、按 `stride` 重算 `bits` 偏移、传递 `version`。
|
||||
* `Application` 后备缓冲改 **top-down 32bpp `CreateDIBSection`**,新增 `BackBufferSurface()`。
|
||||
这就是"整个应用共享一张后台位图"的落地载体;`bits` 只在 CPU 侧合成时使用(画控件只需 `dc + rect`)。
|
||||
* **顺带修掉一个真缺陷**:`Shutdown()` 原本先 `GdiplusShutdown` 再 `DestroyWindow`,
|
||||
而 `DestroyWindow` 期间可能派发 `WM_PAINT` ⇒ `Render()` 在已关闭的 GDI+ 上构造 `Graphics` ⇒ 崩溃。
|
||||
现改为**先销毁窗口 / 注销类、最后 shutdown GDI+**,并给 `Render()` 加了 `m_gdiplusReady` 保护。
|
||||
|
||||
**验证**:8 场景像素哈希与改造前逐一相同;`uicheck` 新增 7 条 `UiSurface` 断言(共 **69/69**)。
|
||||
|
||||
---
|
||||
|
||||
## 8. 明确未做的事(避免误解)
|
||||
|
||||
| 未做 | 原因 |
|
||||
| --- | --- |
|
||||
@@ -186,7 +204,7 @@ flowchart TD
|
||||
|
||||
---
|
||||
|
||||
## 8. 下一步建议(按收益/风险排序)
|
||||
## 9. 下一步建议(按收益/风险排序)
|
||||
|
||||
1. **P3 继:TabBar**(标签 + 「+」+ 重命名内联输入框)→ 再 `PopupMenu` / `ColorPickerPopup` 条目行。
|
||||
判据同 Toolbar:**8+ 场景像素哈希一致 + 功能断言**(点击/悬停/取消、重命名提交与取消)。
|
||||
@@ -199,7 +217,7 @@ flowchart TD
|
||||
|
||||
---
|
||||
|
||||
## 9. 一句话结论
|
||||
## 10. 一句话结论
|
||||
|
||||
> 本阶段**首次把一个现有组件(Toolbar)真的换成了控件树**,并且同时以**像素哈希一致**与**功能断言**证明
|
||||
> 行为未变;同时新增了布局/控件基础层、入库回归网,并把 9 080 行的"万能绘制文件"降到 4 913 行(−46%)。
|
||||
|
||||
Reference in new issue
Block a user