回退 5b52eef 并修复「屏幕不刷新」根因:拖动滚动条卡顿 / 悬停高亮卡住 / 信号拖拽无效果
根因(代码级确认)
- Render() 把界面画进后备缓冲区后用 GetDC + BitBlt 回送窗口,5b52eef 把回送写成
`if (fullFrame) { BitBlt(整窗) } else if (panelOnly) { BitBlt(本帧重绘区域并集) }`,没有兜底 else。
- 「鼠标只在绘图区内移动」的帧(WM_MOUSEMOVE 的 plotOnlyMove 路径只 InvalidatePlotRect)恰好
fullFrame == false && panelOnly == false ⇒ 后备缓冲区被正确重绘,窗口 DC 一个像素都不回送。
- 这一个根因同时造成用户报告的三个症状:悬停光晕卡住(移开不消失)、拖动滚动条不跟手/非常卡顿、
拖拽信号换网格看不到任何结果。
修法
- git reset --hard HEAD~1 撤销 5b52eef(保留 backup-bad-commit 标签供 A/B)。
- 只挑回该提交里与更新区域无关的功能改动(用户明确要求过、本身正确):
* SignalPanel::ExpandGroupForSignal():联动滚动前立刻展开折起的分组(不播展开动画);
* FitAll() / FitSinglePointCluster() 不再复位 Tab().LaneScroll()(适应视图不影响滚动条);
* 右下角「回到最上方」浮动按钮 + 网格滚动到可视区的平滑动画。
- Application.cpp 只保留 3 处最小改动:Render 里把 panelAnimating 计入整帧脏、WM_TIMER 推进
AdvanceBackToTopAnimation() 且保持整窗失效、定时器存活判定带 BackToTopAnimationActive()。
Render 的绘制与 BitBlt 路径逐字节等同于 82b5ebe。
- 彻底删除 m_paintPlot / m_panelDirty / panelOnly / InvalidatePanelRect / 并集回送。
验证(全部离屏执行,不移动真实光标、不抢焦点、不截屏)
- .preflight/diag(新增离屏探针,19/19):窗口移到屏幕外 + WS_EX_TOOLWINDOW + SW_SHOWNOACTIVATE,
保证有真实更新区域与 WM_PAINT 但不影响用户。断言滚动条拖动(滑块与绘图区都在后备缓冲区被重绘)、
悬停光晕出现与消退(像素完全回到基线)、在曲线上按下进入 MOVE_SIGNAL 且拖到另一网格后归属正确。
- .preflight/check 137/137。
- .preflight/diag/verify_blit.ps1(新增源码级护栏,10/10):断言 Render() 的回送块必须有无条件 else、
不得出现 else if、m_paintPlot/m_panelDirty/panelOnly 必须不存在、失效只允许整窗或仅绘图区。
A/B:换回 backup-bad-commit ⇒ 4 项如实失败;换回修复版 ⇒ 10/10。
- make release 零错误零警告。
文档:Documents/agent_mem.md 新增 §9.41、§11.2 第 108–116 条(含 §9.40 与旧 108–114 条的作废标注)
与变更日志一行。
教训(写进记忆):① 离屏探针无法验证「窗口回送 / 合成」(屏幕外 DWM 不合成、窗口 DC 恒为空白)⇒
回送类约束必须有源码级护栏;② 离屏窗口 + TrackMouseEvent 会立刻收到 WM_MOUSELEAVE,探针须丢弃该消息;
③ 网格回收会让下标左移,断言要用锚信号。
This commit is contained in:
1 parent
82b5ebe4f9
commit
f845616938
10 files changed
+460
-8
No files matched your search
@@ -325,6 +325,14 @@ namespace jdi
|
||||
void SignalPanel::ScrollToSignalAnimated(const SignalRef& ref)
|
||||
{
|
||||
EnsureRows();
|
||||
if (!ref.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// ⚠️ **目标信号所在分组若处于折起状态,行集合里根本没有它** —— 无论怎么滚都看不到它。
|
||||
// 用户 2026-10-16 报告:点击网格内的图例触发联动时,被折起的组不会自动展开 ⇒ 联动失效。
|
||||
// 因此先自动展开该分组(立刻生效,不做展开动画:滚动目标需要稳定的行位置)。
|
||||
ExpandGroupForSignal(ref);
|
||||
float desired = m_scrollOffset;
|
||||
if (!SignalScrollTarget(ref, desired))
|
||||
{
|
||||
@@ -334,6 +342,25 @@ namespace jdi
|
||||
StartScrollAnimationTo(desired);
|
||||
}
|
||||
|
||||
bool SignalPanel::ExpandGroupForSignal(const SignalRef& ref)
|
||||
{
|
||||
if (ref.groupIndex < 0 || !IsGroupCollapsed(ref.groupIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SetGroupCollapsed(ref.groupIndex, false);
|
||||
// 该分组若正在播放折起动画,一并作废(目标行的位置会跳回展开态,动画没有意义了)。
|
||||
const int anim = FindGroupAnimation(ref.groupIndex);
|
||||
if (anim >= 0)
|
||||
{
|
||||
m_groupAnims.erase(m_groupAnims.begin() + anim);
|
||||
}
|
||||
// 行集合必须重建(展开后信号行才会出现)——滚动目标依赖它。
|
||||
m_rowsDirty = true;
|
||||
EnsureRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalPanel::AdvanceScrollAnimation()
|
||||
{
|
||||
if (!m_scrollAnimActive)
|
||||
|
||||
Reference in new issue
Block a user