Snapshot before max-resize threshold diagnosis

This commit is contained in:
Codex
2026-04-09 03:23:10 +08:00
parent 77a8fe568a
commit f567369300
25 changed files with 1489 additions and 36 deletions
+137
View File
@@ -0,0 +1,137 @@
# 修改总览-20260409
## 说明
- 本目录用于记录本轮协作中对框架做过的修改。
- 记录范围覆盖:
- 早期未建 Git 基线前的修改
- 已提交到仓库的阶段性修改
- 当前工作区中尚未提交的第二阶段重绘架构与注释整理
- 其中相对最原始版本、但未落到 Git 基线的那部分内容,依据协作过程与当前代码状态回溯整理。
## 阶段概览
1. 初始基线
- 提交:`dde570a`
- 含义:建立仓库后的第一版基线
2. 第一阶段:基础治理与确定性问题修复
- 主要内容:
- 资源所有权收紧
- 析构顺序修正
- `Table / Label / Dialog / Button / TextBox` 等基础问题修复
3. 第二阶段:快照与对话框行为收口
- 提交:`4a6e153`
- 提交:`7f8431a`
- 主要内容:
- 快照“作废”和“回贴”语义拆分
- `Dialog` 在窗口变化时只重新居中
- 模态/非模态对话框的残影、穿透、关闭后 hover 清理等问题修复
4. 第三阶段:统一提交重绘(第一版)
- 提交:`b07a4ec`
- 主要内容:
- 将事件阶段的“改状态”与绘制阶段的“提交”分离
- 窗口开始托管控件在事件分发期间的重绘请求
5. 第四阶段:统一提交重绘(第二版,当前工作区)
- 状态:未提交
- 主要内容:
- 从“整场景统一重绘”推进到“按 root 登记并选择性补画对话框”
-`Canvas / TabControl / Dialog` 建立托管重绘提交语义
- 补充相关注释
6. 测试与文档
- 主要内容:
- `KEY == 4` 综合回归用例
- 日志降噪
- 模板体系与开发记录目录建立
## 记录索引
### BUG
- [BUG-20260409-0001 对话框重绘、快照残留与遮挡交互异常](./BUG/BUG-20260409-0001-对话框重绘快照与遮挡交互异常.md)
- [BUG-20260409-0002 基础控件生命周期与边界条件问题](./BUG/BUG-20260409-0002-基础控件生命周期与边界条件问题.md)
### Fix
- [Fix-BUG-20260409-0001 对话框重绘、快照残留与遮挡交互异常](./Fix/Fix-BUG-20260409-0001-对话框重绘快照与遮挡交互异常.md)
- [Fix-BUG-20260409-0002 基础控件生命周期与边界条件问题](./Fix/Fix-BUG-20260409-0002-基础控件生命周期与边界条件问题.md)
### 功能变更
- [Feature-20260409-0001 基础资源所有权与生命周期收口](./功能变更/Feature-20260409-0001-基础资源所有权与生命周期收口.md)
- [Feature-20260409-0002 Dialog 与 MessageBox 行为调整](./功能变更/Feature-20260409-0002-Dialog与MessageBox行为调整.md)
- [Feature-20260409-0003 输入事件、hover 与遮挡交互调整](./功能变更/Feature-20260409-0003-输入事件与遮挡交互调整.md)
- [Feature-20260409-0004 测试用例与可观测性调整](./功能变更/Feature-20260409-0004-测试用例与可观测性调整.md)
- [Feature-20260409-0005 开发记录与模板体系整理](./功能变更/Feature-20260409-0005-开发记录与模板体系整理.md)
### 模块
- [Module-20260409-0001 Window 托管重绘与覆盖合成机制](./模块/Module-20260409-0001-Window托管重绘与覆盖合成机制.md)
## 覆盖关系
### 核心代码文件覆盖
- `Window.h / Window.cpp`
- 覆盖于:
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- `Feature-20260409-0002`
- `Feature-20260409-0003`
- `Module-20260409-0001`
- `Control.h / Control.cpp`
- 覆盖于:
- `BUG-20260409-0002`
- `Fix-BUG-20260409-0002`
- `Feature-20260409-0001`
- `Module-20260409-0001`
- `Canvas.h / Canvas.cpp`
- 覆盖于:
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- `Feature-20260409-0003`
- `Module-20260409-0001`
- `TabControl.h / TabControl.cpp`
- 覆盖于:
- `Feature-20260409-0003`
- `Feature-20260409-0004`
- `Module-20260409-0001`
- `Dialog.h / Dialog.cpp`
- 覆盖于:
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- `Feature-20260409-0002`
- `Module-20260409-0001`
- `Button.cpp / TextBox.cpp`
- 覆盖于:
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- `Feature-20260409-0003`
- `Table.cpp / Table.h / Label.cpp / MessageBox.cpp`
- 覆盖于:
- `BUG-20260409-0002`
- `Fix-BUG-20260409-0002`
- `Feature-20260409-0001`
- `Feature-20260409-0002`
- `z-testDome.cpp`
- 覆盖于:
- `Feature-20260409-0004`
## 当前状态
- 当前工作区在 `77a8fe5` 之后还有未提交修改。
- 这些未提交修改主要是:
- 第二阶段托管重绘
- 注释补充与校正
- 记录与模板体系整理
@@ -0,0 +1,73 @@
# BUG-20260409-0001
> 适用场景:记录问题本身,不展开完整修复方案。修复内容写入对应的 Fix 文档。
## 基本信息
- ID: BUG-20260409-0001
- 标题: 对话框重绘、快照残留与遮挡交互异常
- 状态:已修复 / 待持续回归
- 严重性:S2
- 优先级:P0
- 模块:Window / Dialog / Canvas / Button / TextBox
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 发现人:协作过程静态审查与测试用例回归
- 关联 Fix IDFix-BUG-20260409-0001
## 问题描述
- 现象:
- 非模态对话框打开后,底层被遮挡控件仍可能收到鼠标事件。
- 模态或非模态对话框在窗口尺寸变化后,可能出现背景快照残留。
- 模态对话框标题区域曾出现抓到底层背景的问题。
- 对话框关闭后,底层按钮 hover 状态可能不能立即恢复。
- 多个按钮快速 hover 切换时,对话框补画链容易闪烁。
- 影响范围:
- 对话框交互正确性
- 重绘层级稳定性
- hover 与点击行为一致性
- 期望结果:
- 对话框始终位于正确层级。
- 被对话框覆盖的底层控件不会误交互。
- resize / 打开 / 关闭过程中无残影、无错位。
- 实际结果:
- 曾出现穿透、残影、错误快照、关闭后 hover 残留、频繁补画闪烁等问题。
## 复现信息
- 前置条件:存在非模态或模态对话框,且下层有可交互控件
- 复现步骤:
1. 打开包含按钮、Canvas、TabControl 的测试窗口。
2. 弹出非模态或模态对话框。
3. 在对话框遮挡区域附近快速移动鼠标,或拖动窗口大小。
- 复现概率:高概率 / 偶现(不同问题不同)
- 最小复现 Demo`z-testDome.cpp``KEY == 2 / 3 / 4`
- 证据:日志、静态推演、用户回归观察
## 初步分析
- 疑似位置:
- `Dialog::handleEvent`
- `Dialog::draw / recenterInHostWindow / clearControls`
- `Window::runEventLoop / pumpResizeIfNeeded / flushManagedRepaint`
- `Button::handleEvent`
- 触发条件:
- 对话框覆盖底层控件
- 窗口 resize
- hover 高频切换
- 对话框打开/关闭后的层级切换
- 相关线索:
- “快照作废”和“回贴旧背景”语义混用
- 事件阶段与绘制阶段原先分离不彻底
- 非模态对话框区域内鼠标事件吞掉后,底层控件拿不到离开消息
## 跟踪信息
- 首次发现时间:本轮协作初期
- 最后更新时间:2026-04-09
- 修复版本:[当前工作区]
- 验证版本:[当前工作区]
- 备注:快速划过多个按钮时一帧内偶发双高亮的问题暂未彻底消除,属于已接受的底层限制
@@ -0,0 +1,71 @@
# BUG-20260409-0002
> 适用场景:记录问题本身,不展开完整修复方案。修复内容写入对应的 Fix 文档。
## 基本信息
- ID: BUG-20260409-0002
- 标题: 基础控件生命周期与边界条件问题
- 状态:已修复 / 待持续回归
- 严重性:S2
- 优先级:P1
- 模块:Control / Window / Table / Label / Button / TextBox / MessageBox
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 发现人:静态审查
- 关联 Fix IDFix-BUG-20260409-0002
## 问题描述
- 现象:
- `Window` 析构时可能先关闭图形环境,再让控件析构访问绘图接口。
- `Table` 在空表头、空数据、列数不一致时存在越界或空状态问题。
- `Label::setText()` 后尺寸与背景快照不能及时同步。
- `MessageBox` 外层曾直接干预 `Dialog` 初始化流程。
- 一些资源所有权和析构职责不够清晰。
- 影响范围:
- 基础稳定性
- 边界输入正确性
- 维护成本
- 期望结果:
- 生命周期安全、边界输入可防御、接口语义清晰
- 实际结果:
- 存在潜在崩溃、越界、状态不一致和维护负担
## 复现信息
- 前置条件:特定表格输入、动态修改文本、窗口关闭、MessageBox 使用链
- 复现步骤:
1. 静态审查相关代码路径。
2. 构造空表头、长于表头的数据行、动态变更 Label 文本。
3. 观察关闭窗口或销毁相关对象时的析构顺序。
- 复现概率:高概率 / 必现(不同问题不同)
- 最小复现 Demo[可选]
- 证据:静态分析、日志、编译验证
## 初步分析
- 疑似位置:
- `Window::~Window`
- `Control` 析构与背景快照恢复链
- `Table::initTextWaH / setData / drawHeader / drawTable`
- `Label::setText`
- `MessageBox::showAsync / showModal`
- 触发条件:
- 边界数据输入
- 动态文本变化
- 对象销毁 / 窗口关闭
- 相关线索:
- 所有权层次混乱
- 空状态防御不足
- 接口暴露超出真实职责
## 跟踪信息
- 首次发现时间:本轮协作初期
- 最后更新时间:2026-04-09
- 修复版本:[当前工作区]
- 验证版本:[当前工作区]
- 备注:字符集相关问题暂未处理,仍按 MBCS 假设工作
@@ -0,0 +1,93 @@
# Fix-BUG-20260409-0001
> 适用场景:记录某个 BUG 的修复方案、影响评估、验证结果与落地信息。
## 关联信息
- Fix ID: Fix-BUG-20260409-0001
- 关联 BUG ID: BUG-20260409-0001
- 修复目标: 收紧对话框快照、遮挡、事件分发和统一提交重绘链
- 状态:已完成 / 待持续回归
- 负责人:Codex 协作修改
- 分支 / 版本:`master`
## 根因分析
- 根因:
- 旧实现中“作废快照”和“回贴旧背景”混在一起,resize 时容易把旧画面贴回屏幕。
- 非模态对话框与底层控件之间缺少明确的事件阻断和 hover 清理机制。
- 重绘长期依赖控件即时局部绘制,导致底层先画、对话框后补,容易闪烁或层级错乱。
- 标题曾作为独立 `Label` 存在,导致额外一层背景快照,时序敏感。
- 触发条件:
- 非模态遮挡下的 hover / click
- 模态或非模态 resize
- 对话框打开 / 关闭
- 为什么之前没发现:
- 问题主要集中在“高频交互 + 对话框遮挡 + resize”组合路径
## 修复方案
- 修复思路:
- 拆分快照语义
- 收紧对话框事件消费
-`Dialog` 在窗口变化时只重新居中
- 将标题绘制并入 `Dialog`
- 把重绘推进到窗口统一收口
- 关键改动:
- `discardBackground()``invalidateBackgroundSnapshot()` 分离
- `Dialog` 标题改为直接绘制,不再使用独立 `Label`
- `Dialog::handleEvent()` 对自身区域内鼠标事件统一吞掉
- 对话框关闭及遮挡场景补发合成 `WM_MOUSEMOVE`,清理底层 hover
- `Window` 引入托管重绘,先重绘受影响 root,再补画相交对话框
- 涉及文件 / 类 / 函数:
- `Window.h / Window.cpp`
- `Dialog.h / Dialog.cpp`
- `Control.h / Control.cpp`
- `Canvas.cpp`
- `TabControl.cpp`
- `Button.cpp`
- `TextBox.cpp`
- 影响的 API / 行为:
- `Dialog` 在窗口变化时的语义固定为“只重新居中,不拉伸”
- 非模态对话框覆盖区域内不再允许鼠标事件穿透到底层
- 关键约束 / 不变量:
- 对话框始终绘制在普通控件之上
- 托管分发期间控件不直接提交绘制
- resize 和对话框开关仍走整场景重绘兜底
## 影响评估
- 影响范围:
- 所有包含 `Dialog`、按钮 hover、遮挡重绘的场景
- 兼容性影响:有(行为更严格,底层控件不再穿透响应)
- 行为变化:有(对话框 resize 只居中;遮挡区域 hover 不再透传)
- 性能影响:有正向变化(减少无意义整场景补画);同时在某些兜底场景仍保留整场景重绘
- 回归风险:
- 托管重绘 root 选择不当可能导致嵌套容器局部重绘异常
- 需持续回归 `Canvas / TabControl / Table / Dialog` 组合场景
## 验证结果
- 验证步骤:
1.`KEY == 2 / 4` 中打开非模态对话框,快速在遮挡区域附近 hover 和点击。
2.`KEY == 3 / 4` 中打开模态对话框并拖动窗口大小。
3. 关闭对话框后观察底层按钮 hover 恢复。
- 验证结果:
- 穿透、残影、关闭后 hover 不恢复等主问题已压住。
- 回归检查:
- 保留对“快速划过多个按钮时偶发一帧双高亮”的已知限制记录。
- 验证证据:
- 静态推演 + 多轮编译验证 + 用户回归反馈
## 落地信息
- Commit:
- `4a6e153`
- `7f8431a`
- `b07a4ec`
- 当前工作区未提交阶段
- PR[可选]
- 发布版本:[可选]
- 备注:该修复跨多个阶段逐步收敛,不是一次性完成
@@ -0,0 +1,88 @@
# Fix-BUG-20260409-0002
> 适用场景:记录某个 BUG 的修复方案、影响评估、验证结果与落地信息。
## 关联信息
- Fix ID: Fix-BUG-20260409-0002
- 关联 BUG ID: BUG-20260409-0002
- 修复目标: 收紧资源所有权,补齐基础边界防御,修正生命周期与接口语义问题
- 状态:已完成 / 待持续回归
- 负责人:Codex 协作修改
- 分支 / 版本:`master`
## 根因分析
- 根因:
- 部分对象持有关系不清晰,析构顺序对 EasyX 上下文敏感。
- `Table / Label` 等基础控件对空状态和动态变化处理不足。
- `MessageBox` 曾通过历史接口越权干预 `Dialog` 初始化。
- 触发条件:
- 析构时机
- 空数据 / 列数不一致
- 动态变更文本
- 为什么之前没发现:
- 很多问题集中在边界输入和静态结构设计,而非主路径功能
## 修复方案
- 修复思路:
- 收紧资源所有权
- 明确析构顺序
- 给空状态和列数不一致加防御
- 让接口更贴合真实职责
- 关键改动:
- `Window` 析构先清空控件树,再 `closegraph()`
- `Control / Window / Button / Table` 中一批资源改为明确所有权
- `Table` 增加空状态、列数规范化、分页下限保护、表高计算
- `Label::setText()` 重新计算尺寸并处理旧快照
- `MessageBox` 移除外层 `setInitialization(true)` 调用
- 涉及文件 / 类 / 函数:
- `Control.h / Control.cpp`
- `Window.h / Window.cpp`
- `Button.h / Button.cpp`
- `Table.h / Table.cpp`
- `Label.cpp`
- `MessageBox.cpp`
- `TextBox.cpp`
- 影响的 API / 行为:
- `Button` 回调 setter 语义收正常
- `MessageBox` 不再依赖外层强制初始化 `Dialog`
- 关键约束 / 不变量:
- 宿主图形上下文必须在控件销毁后再关闭
- 表格行数据必须与表头列数对齐
## 影响评估
- 影响范围:
- 基础控件稳定性与维护性
- 兼容性影响:低
- 行为变化:有(边界输入会被规范化,不再放任异常状态继续传播)
- 性能影响:无明显负担
- 回归风险:
- 主要集中在表格布局与分页按钮链路
## 验证结果
- 验证步骤:
1. 编译 `Window / Control / Table / Label / MessageBox / TextBox` 相关文件。
2. 逻辑推演空表头、长行数据、动态文本变化和窗口关闭链路。
3. 在现有测试用例中回归表格和消息框基本功能。
- 验证结果:
- 已消除确定性越界和明显生命周期风险。
- 回归检查:
- 字符集相关问题暂不在本次修复范围内。
- 验证证据:
- 静态审查 + 编译通过
## 落地信息
- Commit:
- `dde570a` 之后的早期工作区修改
- `4a6e153`
- `7f8431a`
- PR[可选]
- 发布版本:[可选]
- 备注:这部分修复多为基础治理,部分早期修改发生在仓库初始化之前
@@ -0,0 +1,73 @@
# 功能变更 ID: Feature-20260409-0001
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
## 基本信息
- ID: Feature-20260409-0001
- 标题: 基础资源所有权与生命周期收口
- 状态:已完成
- 类型:修改
- 级别:L2 中等
- 模块:Control / Window / Button / Table / Label
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 负责人:Codex 协作修改
## 变更背景
- 背景:
- 初始版本中一部分资源持有关系不明确,析构顺序和边界输入处理存在隐患。
- 目标:
- 提高基础稳定性与维护性。
- 不做什么:[可选]
- 不处理字符集体系切换问题。
## 变更内容
- 变更摘要:
- 收紧资源所有权,调整析构顺序,补齐基础控件边界防御。
- 新增项:[可选]
- `Control` 提供更明确的快照有效性查询和宿主窗口回溯能力。
- 修改项:[可选]
- `Window` 析构顺序调整
- `Table` 行数据规范化、空状态防御、页数保护
- `Label` 动态文本变化处理
- 删除 / 废弃项:[可选]
- `MessageBox` 外层强制 `Dialog` 初始化的做法被移除
- 受影响的文件 / 类 / 函数:
- `Control.h / Control.cpp`
- `Window.h / Window.cpp`
- `Button.h / Button.cpp`
- `Table.h / Table.cpp`
- `Label.cpp`
- `MessageBox.cpp`
- 对外 API / 属性变化:[可选]
- `Button` 回调设置接口语义更正常
## 行为对照
- 变更前:
- 生命周期和边界输入更依赖使用者自觉,异常输入容易直接进入绘制或析构链。
- 变更后:
- 基础控件会主动规范化一部分输入,生命周期顺序更安全。
- 兼容性说明:兼容
- 迁移说明:[可选]
- 无强制迁移要求
## 验证与落地
- 验证方式:
- 静态审查 + 编译验证 + 现有测试用例回归
- 验证结果:
- 主要基础问题已收敛
- 关联 BUG / Fix[可选]
- `BUG-20260409-0002`
- `Fix-BUG-20260409-0002`
- Commit:
- 早期工作区修改 + `4a6e153` + `7f8431a`
- PR[可选]
- 发布版本:[可选]
- 备注:[可选]
- 其中一部分修改早于仓库基线
@@ -0,0 +1,71 @@
# 功能变更 ID: Feature-20260409-0002
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
## 基本信息
- ID: Feature-20260409-0002
- 标题: Dialog 与 MessageBox 行为调整
- 状态:已完成
- 类型:修改
- 级别:L2 中等
- 模块:Dialog / MessageBox / Window
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 负责人:Codex 协作修改
## 变更背景
- 背景:
- 初始版本中 `Dialog` 的初始化、resize、标题绘制和 `MessageBox` 外层调用关系较松散。
- 目标:
- 明确 `Dialog` 行为边界,让其在 resize、显示、关闭、标题更新等场景更稳定。
- 不做什么:[可选]
- 暂不重命名 `setInitialization()` 这类历史接口。
## 变更内容
- 变更摘要:
- `Dialog` 在窗口变化时只重新居中;标题直接由 `Dialog` 自身绘制;`MessageBox` 不再外层强制初始化。
- 新增项:[可选]
- `Dialog::recenterInHostWindow()`
- 修改项:[可选]
- `SetTitle / SetMessage / SetType` 触发重新布局
- `Dialog` 标题不再使用独立 `Label`
- `Dialog` 在模态和非模态场景中的重绘语义被收紧
- 删除 / 废弃项:[可选]
- `MessageBox::showAsync/showModal()` 中对 `setInitialization(true)` 的直接调用已移除
- 受影响的文件 / 类 / 函数:
- `Dialog.h / Dialog.cpp`
- `MessageBox.cpp`
- `Window.cpp`
- 对外 API / 属性变化:[可选]
- `Dialog` 在窗口变化时的对外可观察行为改为“只居中,不拉伸”
## 行为对照
- 变更前:
- `Dialog` resize 时可能重建行为与快照行为混杂,标题区域额外依赖子控件快照。
- 变更后:
- `Dialog` 尺寸由内容决定;窗口变化只重新居中;标题直接绘制,减少一层快照时序问题。
- 兼容性说明:部分兼容
- 迁移说明:[可选]
- 如果外部逻辑曾假设 `Dialog` 会跟随窗口拉伸,现在需要改按“仅居中”理解
## 验证与落地
- 验证方式:
- `KEY == 2 / 3 / 4` 相关场景静态推演与回归
- 验证结果:
- 标题更新、消息框初始化链、resize 后位置语义更稳定
- 关联 BUG / Fix[可选]
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- Commit:
- `4a6e153`
- `7f8431a`
- 当前工作区部分未提交整理
- PR[可选]
- 发布版本:[可选]
- 备注:[可选]
@@ -0,0 +1,75 @@
# 功能变更 ID: Feature-20260409-0003
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
## 基本信息
- ID: Feature-20260409-0003
- 标题: 输入事件、hover 与遮挡交互调整
- 状态:已完成
- 类型:修改
- 级别:L2 中等
- 模块:Window / Canvas / Button / TextBox / Dialog / TabControl
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 负责人:Codex 协作修改
## 变更背景
- 背景:
- 初始版本中,hover、点击、遮挡与重叠控件之间的事件传递不够稳定。
- 目标:
- 建立更一致的鼠标事件消费规则,减少穿透、残留 hover 和无意义重绘。
- 不做什么:[可选]
- 暂不彻底解决“快速划过多按钮偶发一帧双高亮”的底层限制问题。
## 变更内容
- 变更摘要:
- 收紧 `Button / TextBox / Dialog` 的事件消费语义,并补上对话框关闭后及遮挡场景下的 hover 清理。
- 新增项:[可选]
- `Window::dispatchSyntheticMouseMoveToControls(...)`
- 修改项:[可选]
- `Button` 只在合理命中路径上吞掉鼠标事件
- `TextBox` 纯 hover 不再处理
- 非模态对话框覆盖区域内阻断底层穿透
- 对话框关闭后补发合成鼠标移动同步 hover
- 删除 / 废弃项:[可选]
- 大量 hover DEBUG 日志已降噪
- 受影响的文件 / 类 / 函数:
- `Window.cpp`
- `Canvas.cpp`
- `Button.cpp`
- `TextBox.cpp`
- `Dialog.cpp`
- `TabControl.cpp`
- 对外 API / 属性变化:[可选]
- 无新增公开 API,主要是行为语义变化
## 行为对照
- 变更前:
- 遮挡区域 hover/click 可能穿透;对话框关闭后底层 hover 可能残留。
- 变更后:
- 交互更偏向“命中即消费,关闭后同步清理 hover,遮挡区域不透传”。
- 兼容性说明:部分兼容
- 迁移说明:[可选]
- 若旧代码依赖非模态对话框下方控件还能收到事件,这种行为已被收紧
## 验证与落地
- 验证方式:
- `KEY == 2 / 3 / 4` 中对按钮、Tab、Table 分页、对话框关闭链做回归
- 验证结果:
- 主要交互一致性问题已收敛
- 关联 BUG / Fix[可选]
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- Commit:
- `7f8431a`
- `b07a4ec`
- 当前工作区未提交阶段
- PR[可选]
- 发布版本:[可选]
- 备注:[可选]
@@ -0,0 +1,69 @@
# 功能变更 ID: Feature-20260409-0004
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
## 基本信息
- ID: Feature-20260409-0004
- 标题: 测试用例与可观测性调整
- 状态:已完成
- 类型:修改
- 级别:L1 轻量
- 模块:z-testDome / 日志
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 负责人:Codex 协作修改
## 变更背景
- 背景:
- 对话框、遮挡、hover、分页和页签的组合问题需要更有针对性的回归入口。
- 目标:
- 增加一组综合用例,并降低 DEBUG 日志噪音。
- 不做什么:[可选]
- 不改变原有 `KEY == 1 / 2 / 3` 的默认运行逻辑
## 变更内容
- 变更摘要:
- 新增 `KEY == 4` 的综合回归用例,覆盖对话框遮挡、Tab、Table、模态 resize 等场景。
- 新增项:[可选]
- `KEY == 4` 测试分支
- 修改项:[可选]
- hover 相关日志降噪
- 事件日志补充更清晰的事件名
- 删除 / 废弃项:[可选]
-
- 受影响的文件 / 类 / 函数:
- `z-testDome.cpp`
- `Window.cpp`
- `Canvas.cpp`
- `Button.cpp`
- 对外 API / 属性变化:[可选]
-
## 行为对照
- 变更前:
- 回归更多依赖手工拼场景,hover 日志容易刷屏。
- 变更后:
- 有固定综合回归入口,日志更适合看关键路径。
- 兼容性说明:兼容
- 迁移说明:[可选]
- 测试 `KEY == 4` 需手动切换宏值
## 验证与落地
- 验证方式:
- 编译 `z-testDome.cpp`
- 静态推演 `KEY == 4` 控件创建、显示、对话框触发和关闭链
- 验证结果:
- 当前默认 `KEY == 2` 未被带坏,`KEY == 4` 逻辑链自洽
- 关联 BUG / Fix[可选]
- 可作为 `BUG-20260409-0001` 相关问题的回归入口
- Commit:
- 当前工作区未提交阶段
- PR[可选]
- 发布版本:[可选]
- 备注:[可选]
@@ -0,0 +1,69 @@
# 功能变更 ID: Feature-20260409-0005
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
## 基本信息
- ID: Feature-20260409-0005
- 标题: 开发记录与模板体系整理
- 状态:已完成
- 类型:修改
- 级别:L1 轻量
- 模块:文档模板 / 开发记录
- 版本 / 分支:`master`
- 环境:本地工作区
- 负责人:Codex 协作修改
## 变更背景
- 背景:
- 需要对本轮协作中的大量修改建立可持续维护的记录体系。
- 目标:
- 将“问题、修复、功能变化、模块设计”这四类信息分层记录,避免后续继续靠聊天上下文回忆。
- 不做什么:[可选]
- 不把模板设计成覆盖所有场景的一份大而全文档
## 变更内容
- 变更摘要:
- 重写四个文档模板,修正编码内容,并建立统一的开发记录目录。
- 新增项:[可选]
- `开发记录/BUG`
- `开发记录/Fix`
- `开发记录/功能变更`
- `开发记录/模块`
- 修改项:[可选]
- `文档模板` 目录下四个模板重写并重新划分职责
- 删除 / 废弃项:[可选]
- 原模板中“功能变更”和“模块说明”职责重叠的写法已废弃
- 受影响的文件 / 类 / 函数:
- `文档模板/*.md`
- `开发记录/*.md`
- 对外 API / 属性变化:[可选]
-
## 行为对照
- 变更前:
- 模板存在乱码,功能变更和模块说明边界不清,小改动记录成本过高。
- 变更后:
- 模板职责明确,记录粒度更合理,可以持续沉淀协作历史。
- 兼容性说明:兼容
- 迁移说明:[可选]
- 后续新增记录优先按新模板写,不再沿用旧模板内容
## 验证与落地
- 验证方式:
- 读取模板文件确认编码与内容正常
- 创建第一批记录文件验证模板可用
- 验证结果:
- 模板可正常使用,第一批记录已按新体系落地
- 关联 BUG / Fix[可选]
-
- Commit:
- 当前工作区未提交阶段
- PR[可选]
- 发布版本:[可选]
- 备注:[可选]
@@ -0,0 +1,134 @@
# 新增功能模块 / 模块重构
> 适用场景:新增模块、重大模块重构、核心架构能力演进。
> 不适用场景:小接口或轻量功能变更,请使用“功能变更”模板。
## 基本信息
- 模块 IDModule-20260409-0001
- 模块名称:Window 托管重绘与覆盖合成机制
- 状态:已完成 / 待持续回归
- 类型:架构演进
- 所属系统 / 子系统:Window / Control / Dialog 重绘链
- 版本 / 分支:`master`
- 环境:Windows + EasyX + VS2022
- 负责人:Codex 协作修改
## 背景与目标
- 背景:
- 初始框架以控件局部即时重绘为主,非模态对话框与底层控件重叠时,容易出现底层先画、对话框后补的层级问题。
- 当前痛点:
- 对话框遮挡下的 hover / click / tooltip / 分页等交互容易闪烁
- 底层控件和上层对话框在事件里分离绘制,顺序不可控
- 目标:
- 将“事件改状态”和“绘制提交”拆开,由 `Window` 在事件尾统一提交重绘。
- 非目标:[可选]
- 暂不做真正像素级脏区裁剪
- 暂不统一布局系统
## 模块边界
- 职责:
-`Window` 主循环里托管控件重绘请求
- 选择安全的重绘 root
- 在提交阶段维护普通控件与非模态 `Dialog` 的正确层级
- 不负责什么:
- 模态 `Dialog` 自己的内部事件循环
- 布局语义统一
- 字符集问题
- 外部依赖:
- EasyX 绘制接口
- 各控件自身的快照恢复能力
- 对外能力 / API:
- `Window::requestManagedRepaint(Control* source)`
- `Window::flushManagedRepaint()`
- `Control::getManagedRepaintRoot()`
- `Control::commitManagedRepaint()`
- 关键数据 / 状态:
- `managedDispatchActive`
- `managedSceneDirty`
- `managedRepaintItems`
## 设计说明
- 核心流程:
1. `Window::runEventLoop()` 开始输入分发前,进入 `managedDispatchActive = true`
2. 控件在 `handleEvent()` 中只改状态并通过 `requestRepaint()` 上报
3. `Window::requestManagedRepaint(source)` 把 source 转换成 `root + coverage`
4. 事件收口时 `flushManagedRepaint()` 按层级提交 root
5. 最后补画和脏区相交的非模态 `Dialog`
- 关键对象 / 类关系:
- `Window`:重绘调度中心
- `Control`:提供宿主窗口回溯与 root 选择语义
- `Canvas / TabControl / Dialog`:作为安全重绘 root 的主要容器
- 生命周期:
- 托管重绘项只存在于当前分发轮次
- `clearManagedRepaintState()` 在 flush、resize 收口、对话框开关后的整场景重绘后清空
- 事件 / 渲染 / 数据流:
- 事件:Dialog 优先,普通控件其次
- 渲染:受影响普通 root 先画,Dialog 后补
- 数据流:leaf control -> requestRepaint -> Window registry -> flush
- 关键不变量:
- 分发期不直接提交托管重绘
- 顶层普通控件的提交顺序必须服从 `Window::controls` 的 z-order
- 对话框始终绘制在普通控件之上
- 降级 / 回退策略:[可选]
- `resize`、对话框打开/关闭等全局变化仍走整场景重绘
## 实现与影响
- 关键实现点:
- `Control` 增加 `hostWindow``getManagedRepaintRoot()``commitManagedRepaint()`
- `Window` 增加 `ManagedRepaintItem` 队列
- `Canvas / TabControl / Dialog` 提供局部可提交与升级为整 root 重画的判断
- 涉及文件 / 类 / 函数:
- `Window.h / Window.cpp`
- `Control.h / Control.cpp`
- `Canvas.h / Canvas.cpp`
- `TabControl.h / TabControl.cpp`
- `Dialog.h / Dialog.cpp`
- 兼容性影响:
- 行为层面更严格,底层控件不再依赖旧的“即时局部重绘”副作用
- 性能影响:
- 相比整场景重绘更细
- 相比纯即时局部重绘更稳定
- 在全局变化场景仍保留整场景兜底
- 风险点:
- root 选择错误会导致局部重绘不完整
- 嵌套容器组合场景需持续回归
## 测试与验证
- 测试范围:
- 非模态遮挡下的按钮 hover / click
- `Canvas / TabControl / Table` 组合场景
- 模态与非模态对话框 coexist 场景
- 验证步骤:
1. 编译 `Control / Canvas / TabControl / Dialog / Window` 相关源文件。
2. 回归 `KEY == 2 / 3 / 4` 的对话框与遮挡场景。
3. 检查对话框关闭、resize、hover 清理和局部重绘顺序。
- 验证结果:
- 第二阶段架构已落地,核心编译通过,主问题链路已被压住。
- 已知限制 / 遗留问题:[可选]
- 快速划过多个按钮时偶发一帧双高亮,当前接受为底层限制
- 仍未推进到真正像素级脏区裁剪
## 落地信息
- 关联功能变更 ID[可选]
- `Feature-20260409-0002`
- `Feature-20260409-0003`
- 关联 BUG / Fix[可选]
- `BUG-20260409-0001`
- `Fix-BUG-20260409-0001`
- Commit:
- `b07a4ec`
- `77a8fe5`
- 当前工作区未提交阶段
- PR[可选]
- 发布版本:[可选]
- 相关文档:[可选]
- `00-修改总览-20260409.md`