修复信号面板滚动条跟随、工具栏连点丢状态、图层竖向网格线步长、多网格单点自适应与单点信号拖拽
用户 2026-10-15 报告的五个问题,逐一给出根因与修法(详见 Documents/agent_mem.md §9.32):
1. 拖动信号面板滚动条、鼠标移到绘图区后“滑块卡在原地不动”
根因:Application::WM_MOUSEMOVE 的 plotOnlyMove 只看 inPlot && m_mouseOverPlot,
拖滚动条进入绘图区后判定“本帧只影响绘图区” ⇒ 面板滚动偏移已变却从不重绘。
修法:新增 draggingNonPlot(正在拖非绘图区组件时一律走完整失效)。
2. 工具栏快速连点 / 双击丢状态
根因:(a) 窗口类带 CS_DBLCLKS,快速第二次按下被合成 WM_LBUTTONDBLCLK 而工具栏未处理
(那一次按下完全丢失);
(b) HandleMouseMove 只要鼠标不在工具栏上就调 OnMouseLeave(),清掉 m_pressedIndex
⇒ 按住期间从按钮边缘划出再回到按钮松手不会触发任何动作。
修法:WM_LBUTTONDBLCLK 命中工具栏时按“按下”处理;m_activeTarget == TOOLBAR 期间不调 OnMouseLeave()。
3. 网格叠底:拖拽期间竖向网格线错位 / 丢失,操作信号样式时“闪烁”
根因:PaintLane 的竖向主刻步长由 Tab().ViewMin/ViewMax 推出,而渲染信号图层时该区间已被
RenderLaneLayerRegion 改成“宽窗口”(≈2× 前台)⇒ 图层辅助线步长 2×、位置与前台不同、
“与主刻重合则跳过”的判据也随之错位 ⇒ 贴图后网格线错位 / 整条丢失,
并在“图层帧 ↔ 结算帧”之间来回切换时闪烁。
修法:新增 m_renderTimeStep,由 RenderLaneLayerRegion 用前台视界跨度算好传入
(与纵向 m_wideTickSpan/m_wideTickHeight 同一思路),PaintLane 优先使用它。
4. 多个网格、每个网格只有一个数据点时「适应视图」把数据点甩飞
修法:新增 FitSinglePointLanes(),按用户给出的规则:
* 左右边界 = 所有网格中最左 / 最右数据点的时间,再向外各偏“一个网格小格”的时间跨度;
* 逐网格 Y 自适应,并在纵向上下各留“一个 Y 小格”的高度;
* 全部数据点在同一时刻时 ⇒ 时间跨度 1s 且以该时刻居中(与首个单点信号的初始视图对齐);
* 某网格只有一个取值 ⇒ 该网格 Y 跨度 1 且居中。
仅在全部可见信号都是单点(finiteCount == 1)时启用,否则交回常规 FitAll。
5. 单点信号的悬停高亮与拖拽换网格
修法:HitTestSignal 新增单点分支(SinglePointScreenPos + 容差 = max(常规容差, 该点绘制半径));
悬停用环状光晕且不改鼠标形状(QueryCursor 不查 HitTestSignal),按下拖拽后才改 IDC_SIZEALL;
拖拽虚影对单点信号回退为实心点 + 环。
验证(全部离屏,不占用鼠标 / 键盘 / 屏幕):
- .preflight/check(SW_HIDE + 只注入合成消息 + 进程/线程 BELOW_NORMAL)**67/67 通过**,连跑 3 次稳定。
其中 [C] 直接量“宽基底图层位图自身”的网格线间距(图层主刻 123px vs 前台 122px、辅助线 25px vs 25px),
并断言拖拽帧确实来自宽基底贴图路径(m_wideLastValid)。
- A/B 判别:回退上述六处修复后 **17 项如实失败**([C] 辅助线 49px vs 25px、20 vs 40 条、最大偏移 539px)。
- make release:三个改动文件重新编译 **零警告**;链接用临时 `make release TARGET_FILE_NAME=Target_check` 通过。
同步记忆:Documents/agent_mem.md 新增 §9.32、§11.2 第 64–68 条硬约束、变更日志末行。
This commit is contained in:
1 parent
68d8b7ede6
commit
aee3a388b5
5 files changed
+541
-40
No files matched your search
@@ -447,6 +447,52 @@ namespace jdi
|
||||
*/
|
||||
bool FitSinglePointSignal();
|
||||
|
||||
/**
|
||||
* @brief 「网格内只显示单点信号」时的自适应(含多个网格各只有一个数据点)。
|
||||
*
|
||||
* 用户要求(2026-10-15):多网格、每个网格只有一个数据点时,适应视图必须保证
|
||||
* **所有散点都在屏幕内**:
|
||||
* * 时间轴左边界 = 所有点中最早的时刻 **再向左偏移一小格**(一小格 = 该视界下
|
||||
* 主刻度 / 五等分,与网格叠底同源);右边界同理向右偏移一小格;
|
||||
* * 若**所有点都在同一时刻**(最极端情况),按“首个网格加载为单点信号”的方式对齐
|
||||
* (时间跨度 1s、居中);
|
||||
* * 逐网格的 Y 轴:网格内若有**取值不同**的多个单点信号,纵向同样在各边界留出一小格
|
||||
* (`LaneValueGridCell`);只有一个取值时跨度 1、居中。
|
||||
*
|
||||
* 任一网格里存在非单点的可见信号时**不适用**(返回 false,交回常规整段自适应)。
|
||||
*
|
||||
* @return 已按单点规则完成自适应返回 true。
|
||||
*/
|
||||
bool FitSinglePointLanes();
|
||||
|
||||
/**
|
||||
* @brief 取某信号**唯一的有效数据点**(时刻 + 原始取值)。
|
||||
*
|
||||
* 优先用加载时缓存的稀疏点;没有缓存时逐个采样找(单点信号的采样数组必然很短)。
|
||||
*
|
||||
* @param [IN] signal 目标信号。
|
||||
* @param [IN] axis 该信号使用的时间轴。
|
||||
* @param [OUT] time 数据点时刻。 @param [OUT] value 数据点原始取值。
|
||||
* @return 取到有效点返回 true。
|
||||
*/
|
||||
bool SinglePointOfSignal(const SignalData& signal, const TimeAxis& axis, double& time,
|
||||
double& value) const;
|
||||
|
||||
/**
|
||||
* @brief 时间轴**一小格**对应的时间跨度(= 主刻 / 五等分,与网格叠底同源)。
|
||||
* @param [IN] span 参考跨度。
|
||||
* @return 一小格的时间跨度(无法判定时返回 0)。
|
||||
*/
|
||||
double TimeGridCellSeconds(double span) const;
|
||||
|
||||
/**
|
||||
* @brief 某网格**一小格**对应的幅值跨度(与网格叠底的横向刻度同一套算法)。
|
||||
* @param [IN] span 参考幅值跨度。
|
||||
* @param [IN] laneHeight 网格高度(像素,决定纵向刻度密度)。
|
||||
* @return 一小格的幅值跨度(无法判定时返回 0)。
|
||||
*/
|
||||
double LaneValueGridCell(double span, float laneHeight) const;
|
||||
|
||||
/**
|
||||
* @brief 以给定倍率缩放时间轴(以视图中心为锚点)。
|
||||
* @param [IN] factor 缩放倍率,大于 1 表示放大。
|
||||
@@ -2483,21 +2529,44 @@ namespace jdi
|
||||
* @brief 绘制某条信号的悬停/拖拽光晕(按缓存的折线模式选择最省的画法)。
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
* @param [IN] resolved 已解析的信号。
|
||||
* @param [IN] lane 该信号所在网格(单点信号需要它把数据点换算到屏幕坐标)。
|
||||
* @param [IN] cached 该信号的折线缓存项(包络带模式下会走带外扩填充)。
|
||||
*/
|
||||
void PaintSignalHaloFor(gd::Graphics& g, const ResolvedSignal& resolved,
|
||||
void PaintSignalHaloFor(gd::Graphics& g, const ResolvedSignal& resolved, const LaneVisual& lane,
|
||||
const PolylineCacheEntry& cached);
|
||||
|
||||
/**
|
||||
* @brief 绘制某条信号的悬停/拖拽光晕(折线描边版本)。
|
||||
*
|
||||
* ⚠️ 只有**单个有效数据点**的信号没有折线可描边(其默认样式是「点线」),
|
||||
* 此时改为围绕那个数据点画一圈强调色圆环 —— 否则悬停时完全没有视觉反馈。
|
||||
*
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
* @param [IN] resolved 已解析的信号。
|
||||
* @param [IN] lane 该信号所在网格。
|
||||
* @param [IN] points 折线顶点。
|
||||
* @param [IN] breaks 每段折线的起始下标。
|
||||
*/
|
||||
void PaintSignalHalo(gd::Graphics& g, const ResolvedSignal& resolved,
|
||||
void PaintSignalHalo(gd::Graphics& g, const ResolvedSignal& resolved, const LaneVisual& lane,
|
||||
const std::vector<gd::PointF>& points, const std::vector<std::size_t>& breaks);
|
||||
|
||||
/**
|
||||
* @brief 单点信号那个数据点绘制时的半径(与散点绘制同源)。
|
||||
* @param [IN] resolved 已解析的信号。
|
||||
* @return 半径(像素)。
|
||||
*/
|
||||
float SinglePointDotRadius(const ResolvedSignal& resolved) const;
|
||||
|
||||
/**
|
||||
* @brief 取某信号**唯一数据点**在屏幕上的位置(含时间偏移与「调整」变换)。
|
||||
* @param [IN] resolved 已解析的信号(要求 `finiteCount == 1`)。
|
||||
* @param [IN] lane 该信号所在网格。
|
||||
* @param [OUT] out 屏幕坐标。
|
||||
* @return 取到有效位置返回 true。
|
||||
*/
|
||||
bool SinglePointScreenPos(const ResolvedSignal& resolved, const LaneVisual& lane,
|
||||
gd::PointF& out) const;
|
||||
|
||||
/**
|
||||
* @brief 计算某网格图例中 GX 编号徽标的矩形(绘制与命中测试共用,保证一致)。
|
||||
* @param [IN] laneIndex 网格下标。
|
||||
@@ -2886,6 +2955,18 @@ namespace jdi
|
||||
*/
|
||||
double m_wideTickSpan = 0.0;
|
||||
float m_wideTickHeight = 0.0f;
|
||||
/**
|
||||
* @brief 渲染「信号图层(宽基底)」时使用的时间主刻步长(秒);0 = 按当前视界自行推算。
|
||||
*
|
||||
* ⚠️ **必须由 `RenderLaneLayerRegion` 显式传入(前台视界跨度算出的步长)**:
|
||||
* 图层画布比前台宽约一倍(左右各半屏),而 `Tab().ViewMin/ViewMax` 在图层的临场渲染里
|
||||
* 被改成了**宽窗口**区间 —— 若 `PaintLane` 直接拿这个区间去 `NiceStep`,算出的主刻步长会
|
||||
* 比前台大(往往正好 2 倍),于是图层里的竖向网格线(含五等分辅助线)**落在与前台不同的位置**、
|
||||
* 并且“与主刻重合则跳过”的判据也错位 → 用户看到网格线**错位/部分整条丢失**、
|
||||
* 且在“拖拽帧(用图层)”与“结算帧(整幅重绘)”之间来回切换时**闪烁**。
|
||||
* 与纵向的 `m_wideTickSpan/m_wideTickHeight` 是同一套思路(那两处已经做对了)。
|
||||
*/
|
||||
double m_renderTimeStep = 0.0;
|
||||
|
||||
/**
|
||||
* @brief 本次 `PaintLane` 只绘制「装饰」(Y 轴刻度胶囊 + 图例 + 网格分界线)。
|
||||
|
||||
Reference in new issue
Block a user