Files
Just-DataInspector/Utilities/Inc/Utf8Util.hpp
T
DeepSeek V4.1 Flash 8801c8f019 修复缩放视界下拖拽与改色卡顿、加载字节进度、光标越界三角与中心轴均值滤波统一
1. 修复选区放大后的拖拽/改色卡顿(先实测再修,不猜)
   - 用离屏探针量化:缩放视界下一帧要画约 250 条网格线,GDI+ DrawLine 每条 0.1~0.19ms,
     整帧 26.4ms;而包络带填充本身只要 0.36ms,真正的瓶颈是逐条直线调用。
   - 网格线、时间轴刻度、绘图区边框、网格分隔线全部改为 GDI 批量 1px 直线绘制
     (一次 SaveDC/IntersectClipRect/创建画笔,逐段 MoveToEx/LineTo);
     纵轴数值胶囊改为把所有圆角矩形合并成一个路径、只调用一次填充。
   - 半透明网格线颜色先用底色预混成不透明色,否则 GDI 无法绘制透明度;
     GDI 绘制不受 GDI+ 裁剪约束,批量绘制一律显式设置裁剪矩形。
   - 实测:缩放视界下场景缓存失效帧 26.4 -> 8.25ms,改色应用 7.1 -> 3.15ms,
     缓存命中帧 2.06 -> 0.30ms。

2. 读取文件时显示"已读取 / 总大小 百分比"
   - 解析进度回调扩展为携带真实字节数(已读字节、文件总字节);
     列重组等没有字节可计的阶段只显示百分比。
   - 新增字节数格式化:单位在 GB / MB / KB 之间自适应,只输出数字与单位;
     已读大小随进度自动切换单位。
   - 进度浮层按"已读取 / 文件总大小  百分比"显示,两个大小与百分比都保留两位小数,
     完全取代原来的整数百分比。

3. 网格编号拖拽重排的绘制修复
   - GX 编号悬停时保持普通箭头光标(不再变成四向箭头),按下拖拽时才使用上下箭头。
   - 拖拽时先把整幅静态场景(含主时间轴)贴回,再把目标槽位高亮、被拖网格的轮廓与
     投影裁剪在绘图区内,因此拖到工具栏甚至更上方、或拖到时间轴及下方都不再出现
     残留与错乱。

4. 网格 Y 轴数值只在完全移出可视区时才不绘制
   - 原来只要碰到边界就整条不画;现在按可见范围裁剪胶囊与数值,
     部分可见时绘制未被遮挡的部分。

5. 边沿计数横向光标的读数与越界指示
   - 幅值读数右移,让开横线左端的三角把手,不再遮挡。
   - 幅值超出视界时(横线贴边显示)在读数上方/下方绘制方向三角,
     并且与读数水平居中对齐。

6. 常规光标读数越界与双光标叠放
   - 光标滞留在视界之外时,时间读数同样绘制方向三角。
   - 双光标读数重叠时按时间值排序:小值在上、大值在下(原来固定把第二个上移,
     左右光标交换后会显示成大的在上)。
   - 双光标同时越界到同一侧时,两条时间读数与时间差值读数在同一列垂直对齐,
     并为差值读数绘制方向三角;叠放间距按三角深度放宽,三角不会再压在相邻读数上。

7. 中心轴边沿计数与均值滤波统一
   - 参数由单一的"平滑点数 N"改为按信号的"均值点数 X + 阶数 N",与实验性功能中的
     均值滤波完全同构(同样的命名、同样的作用、同样的曲线实现),
     两条曲线逐位一致,光标处的取值标注规则也统一。
   - 浮动面板改为自上而下的逐信号条目,每个条目三排:
     第一排信号名与复选框,第二排均值点数与阶数输入框,第三排该信号的上升沿/下降沿统计;
     取消勾选即不显示该信号的参数编辑与统计结果,启用时默认只勾选第一个可见信号。
   - 网格重建继承、拆分网格、信号插入/删除的下标修正与场景缓存指纹都同步覆盖新条目。

测试:离屏自动验证套件新增一组检查(字节数格式化、解析进度字节、编号悬停/拖拽光标、
双光标读数排序与对齐、中心轴三排布局与参数、横向光标越界三角、加载浮层渲染等),
合计 241 项检查全部通过;验证过程不显示窗口、不移动鼠标键盘、不抓屏。
2026-10-10 16:47:05 +08:00

136 lines
4.5 KiB
C++

#ifndef __UTF8_UTIL_HPP__
#define __UTF8_UTIL_HPP__
#include <windows.h>
#include <cstddef>
#include <string>
#include <vector>
namespace jdi
{
/**
* @brief 将 UTF-8 编码的字节序列转换为宽字符串(UTF-16LE)。
* @param [IN] text UTF-8 文本起始地址。
* @param [IN] length 文本字节数,传入负值表示按 '\0' 结尾自动计算长度。
* @return 转换后的宽字符串,输入非法时返回空字符串。
*/
std::wstring Utf8ToWide(const char* text, int length = -1);
/**
* @brief 去除字符串首尾的空白字符(含制表、换行与不间断空格)。
* @param [IN] text 待处理文本。
* @return 去除首尾空白后的新字符串。
*/
std::wstring Trim(const std::wstring& text);
/**
* @brief 去除字符串首尾的成对引号(单引号或双引号)。
* @param [IN] text 待处理文本。
* @return 去除引号后的新字符串。
*/
std::wstring StripQuotes(const std::wstring& text);
/**
* @brief 仅针对 ASCII 字母执行小写转换(其余字符原样保留)。
* @param [IN] text 待处理文本。
* @return 转换后的新字符串。
*/
std::wstring ToLowerAscii(const std::wstring& text);
/**
* @brief 判断字符串是否包含指定子串(ASCII 大小写不敏感)。
* @param [IN] text 被检索文本。
* @param [IN] needle 子串文本。
* @return 包含返回 true,否则返回 false。
*/
bool ContainsInsensitive(const std::wstring& text, const std::wstring& needle);
/**
* @brief 从字符区间中解析一个双精度浮点数(允许尾部存在非数字残留字符)。
* @param [IN] begin 区间起始指针。
* @param [IN] end 区间结束指针(不包含)。
* @param [OUT] value 解析结果输出。
* @return 解析成功返回 true,区间为空或完全无法识别时返回 false。
*/
bool TryParseDouble(const char* begin, const char* end, double& value);
/**
* @brief 以固定小数位格式化数值。
* @param [IN] value 待格式化数值。
* @param [IN] decimals 小数位数。
* @return 格式化后的文本。
*/
std::wstring FormatNumber(double value, int decimals);
/**
* @brief 把字节数格式化为自适应单位的文本(GB / MB / KB),保留两位小数。
*
* 单位阀值:1 GB = 1024 MB、1 MB = 1024 KB;小于 1 KB 时也按 KB 显示。
* 只输出"数字 + 单位"(如 "1.69 GB"),便于拼接为"已读取 / 总量"。
*
* @param [IN] bytes 字节数。
* @return 形如 "812.34 MB" 的文本。
*/
std::wstring FormatByteSize(unsigned long long bytes);
/**
* @brief 以自适应有效位格式化数值(NaN/Inf 会被转换为可读文本)。
* @param [IN] value 待格式化数值。
* @return 格式化后的文本。
*/
std::wstring FormatValue(double value);
/**
* @brief 依据坐标轴刻度步长格式化刻度标签。
* @param [IN] value 刻度值。
* @param [IN] step 刻度步长,用于推断所需小数位。
* @return 刻度标签文本。
*/
std::wstring FormatTick(double value, double step);
/**
* @brief 将整数格式化为带千位分隔符的文本。
* @param [IN] value 待格式化整数。
* @return 格式化后的文本。
*/
std::wstring FormatCount(unsigned long long value);
/**
* @brief 计算“美观”的坐标轴刻度步长(1/2/5 乘以 10 的整数次幂)。
* @param [IN] range 坐标轴数值跨度,必须为正数。
* @param [IN] targetTicks 期望的刻度数量。
* @return 刻度步长,输入非法时返回 1.0。
*/
double NiceStep(double range, int targetTicks);
/**
* @brief 依据范围与步长生成刻度值序列。
* @param [IN] minValue 范围下限。
* @param [IN] maxValue 范围上限。
* @param [IN] step 刻度步长。
* @param [OUT] ticks 输出刻度序列(按升序排列)。
*/
void BuildTicks(double minValue, double maxValue, double step, std::vector<double>& ticks);
/**
* @brief 将文本复制到系统剪贴板。
* @param [IN] owner 剪贴板所有者窗口句柄,允许为空。
* @param [IN] text 待复制文本。
* @return 复制成功返回 true。
*/
bool CopyTextToClipboard(HWND owner, const std::wstring& text);
/**
* @brief 从系统剪贴板读取文本。
* @param [IN] owner 剪贴板所有者窗口句柄,允许为空。
* @param [OUT] text 读出的文本,剪贴板无文本时清空。
* @return 读到非空文本返回 true。
*/
bool PasteTextFromClipboard(HWND owner, std::wstring& text);
} // namespace jdi
#endif // __UTF8_UTIL_HPP__