Windows 截图标注 + 贴图工具。 C++20/Qt6 界面 + Rust 原生核心, 免安装绿色版(一个文件夹)
当前版本:1.3.0。版本号只有 cpp/sys/defaults.hpp 的 VERSION 一处:
CMake 在 configure 时读它展开成 exe 的版本资源(assets/zpin.rc 是模板,
构建期生成到 build 目录),关于页显示的也是同一个常量。
- Rust(
rust/):承接 C++ 跑不快或 Win32 交互深的纯计算——整屏高斯模糊 (三轮盒滤波,O(n))、屏幕抓取、UIA 界面元素吸附、可见窗口矩形枚举、 文字识别(PP-OCRv6 small,ONNX 推理走ort,模型文件在assets/models/)、 表格识别(PicoDet 版面模型找出表格区域,先检测表格边框线还原真格子——合并跨度与 对齐都来自线;无边框表检不出线时回落到 OCR 框投影,复用同一套文字模型)、 HTTP(S) 下载(自动更新走 WinHTTP)。 经cxx桥接编成静态库,CMake 会先跑cargo build --release再链进 exe。 - C++/Qt6 Widgets(
cpp/):界面、事件、绘制、托盘、热键、贴图窗口全部在这层。 之所以不是纯 Rust:官方 Qt Bridges 的 Rust Bridge 只对接 QML,不支持 Qt Widgets,而本工具是逐像素工具(遮罩/放大镜/手绘面板都要按物理像素画)。 - Win32 边界:一律走
cpp/sys/win32util.hpp与rust/src/*,不散落裸调用。
- 截图:全局快捷键/托盘发起,多屏混合 DPI 支持;悬停自动吸附界面元素 (UIA:按钮/编辑框/链接/图片/列表项/选项卡…,元素过大时回退整窗),UIA 认不出 来时按画面吸附内容块(取景框外圈主色当背景,连通块长出边界:网页里的图片、 卡片、自绘界面的控件都能框住;被取景框切断的块宁可不吸也不给假边界), 再回退整窗;窗口矩形取 DWM 可见边界、不多出一圈隐形边框;UIA 查询在常驻 工作线程进行(查询瞬间遮罩窗在该线程临时穿透),UI 线程只收几何结果、零 COM 等待,慢 provider 自动熔断不卡交互;吸附建议框挖空透出真实画面, 元素/窗口间切换带短过渡动画。 框选/移动/缩放时边与角自动对齐屏幕和其它窗口的边、中线(红色参考线,可关)。
- 放大镜与取色:拖动边角/手柄调整时自动出现 10 倍放大镜(像素网格 + 中心红框 + 坐标色值信息条,贴边自动翻转);按 Alt 随时召唤/收起;截图时随时按 C 复制光标处颜色(#RRGGBB,画面顶部弹绿色提示)。
- 框选:按住拖拽即自由框选(吸附只管悬停预览与单击,不干扰拖动)、单击即吸附; Space 关掉悬停吸附、Tab 轮换检测层级 自动→仅整窗→仅界面元素(两者仅在未 框选时有效,下次截图自动复位);框选后 8 角/边手柄缩放、 选区外自动扩选、方向键微调(Shift 加速)、Ctrl+方向 沿该侧扩选、 Tab(已框选)循环手柄;工具栏首位是「选择 / 编辑」:点已画图形改形状, 空白处拖动重新选框。
- 标注:画笔、荧光笔、直线、虚线(分隔线 / 指示范围)、 曲线(拖出后拖线身弯出弧度,两端手柄调端点)、单箭头、双向箭头、 矩形、椭圆、标注气泡、文本、马赛克、 高斯模糊(与马赛克同为框选一块区域,效果更平滑)、 聚光灯(框选一块保持原样,框外整幅压暗;可框多块,亮区互不干扰)、 序号标记(自动递增,撤销/擦除后新序号补位)、橡皮擦(对象级擦除, 悬停红框预览将被擦除的图形)、 智能擦除(框选一块区域,用周围的背景把内容重建掉——去水印/杂物, 后台内容感知填充,计算中红框占位);12 色板 + 三档粗细;撤销/重做(Ctrl+Z/Y)。 矩形/椭圆、直线/虚线/曲线、单/双向箭头、画笔/荧光笔、马赛克/高斯模糊/聚光灯、 橡皮擦/智能擦除、文本/气泡/序号 各共用一个分裂按钮(点图标用上次那个,右键展开切换,图标右下角带小三角); 识别文字 / 识别表格 / 一键脱敏 / 长截图收进 ⋮ 菜单 (点 ⋮ 再点一次即收起),悬停图标弹中文气泡。 已画图形可二次编辑:不选工具时点中即选中,可整体拖动、拖端点改形状、 换颜色/粗细、Del 删除(均可撤销);曲线拖线身直接弯出弧度; 文本/气泡字号跟随「粗细」档位。 移动选区时已画标注跟着框走(标注锚定在选区上);文字/气泡输入框随内容自适应大小。
- 多种出口:Enter 复制;工具栏一排上有「贴图」(钉到桌面)、「保存」(一键存到默认 目录,气泡回执路径)、「另存为」;**「识别文字」「识别表格」(结果同时带 HTML 与 制表符两份,粘进 Excel/WPS 就是表格)、「一键脱敏」(手机号/邮箱/身份证自动 打码,本地 OCR + 正则)、「长截图」(你自己滚动页面,工具实时拼接)**收在 ⋮ 菜单; PP-OCRv6 small 模型随包附带、识别过程不联网。 识别结果按版式归并:被排版折断的软换行合成整段、列表与菜单项仍逐行、两栏不会互相 粘连,中英交界自动补空格。 写盘与识别都在后台线程,保存/识字瞬间界面不卡。
- 贴图:置顶无边框窗口;光标锚点滚轮缩放(≥100% 最近邻、<100% 平滑、<50% 缩略图); 不透明度/边框/阴影/发光;旋转/翻转/灰度;双击贴图 = 隐藏; 右键「标注」直接在贴图上画图(与截图标注同一套工具:画笔/荧光笔、矩形/椭圆、 直线/虚线/曲线、单/双向箭头、文本/气泡/序号、马赛克/模糊/聚光灯、 橡皮擦/智能擦除,撤销/擦除/二次编辑齐备,几何变换前自动烘焙进底图);右键还有识别文字与一键脱敏 (命中的手机号/邮箱/身份证压成可撤销的马赛克标注);鼠标穿透(点击落到下层窗口,托盘一键恢复)。
- 托盘:截图入口 + 隐藏/显示全部贴图
- 截图历史墙(缩略图:贴图化 / 保存 / 复制 / 删除 / 清空)+ 恢复贴图可点击(穿透兜底)。
- 帮助:设置 → 帮助(托盘只留「设置」一个入口),顶部一排分段主题 (快速上手 / 框选截图 / 标注工具 / 贴图),键位实时读配置(改键即同步)。
- 设置:常规/截图/贴图/输出/快捷键/帮助/关于七页(「界面」并入「常规」);热键即时注册、冲突标红; 文件名模板实时预览;每页可独立恢复默认。
- 自动更新:数据源 GitHub Releases。启动静默检查(24 小时节流,可在 设置 → 关于 关闭),发现新版本弹气泡(点击直达关于页);关于页可手动检查、 一键下载 zip 并换装重启(等进程退出后覆盖文件再拉起新版)。
| 动作 | 默认键 |
|---|---|
| 全屏截图 | Ctrl+Shift+A |
| 框选截图 | Ctrl+Shift+X |
| 窗口截图 | Ctrl+Shift+W |
| 隐藏/显示全部贴图 | Ctrl+Shift+H |
默认键避开了 F1/F3、Alt+L 等常被系统/驱动/其它工具占用的组合。 从旧版本升级时,启动会自动把未被用户修改过的旧默认键迁移到上表组合。 在 设置 → 快捷键 里修改键位后立即生效:托盘菜单右侧的快捷键提示、 帮助窗口里的键位表都会同步显示新键(无需重启)。
选区内的快捷键:Enter 复制、双击 复制、Ctrl+S 快速保存、Ctrl+C 复制、Ctrl+Z/Y 撤销/重做、 Del 删除选中的标注图形、方向键微调(Shift 加速、Ctrl+方向 扩选、Tab 循环手柄)、 Alt 召唤放大镜、C 复制光标处色值、Space 关掉悬停吸附、Esc 取消。
贴图窗快捷键:Ctrl+C 复制、Ctrl+S 另存为、Ctrl+0 实际大小、Ctrl+R 重置变换、 Ctrl++ / Ctrl+- 缩放、Ctrl+T 旋转、Esc 隐藏、Del 销毁。
- 全屏截图(Ctrl+Shift+A / 托盘「全屏截图」)= 一键截取全屏:不进选区界面,抓屏后 直接复制到剪贴板(同样进截图历史,可再取)。
- 框选截图(Ctrl+Shift+X / 托盘「框选截图」)= 框选:
- 进入截图后光标始终可见(十字准星),鼠标在哪就从哪开始框选。
- 按住左键拖动 = 自由框选:拖动本身一直是自由的,悬停吸附不会把你的框拽到 元素上(边和角会自动对齐屏幕与其它窗口的边、中线,命中时画红色参考线, 可在 设置 → 截图 关闭);
- 单击 = 吸附选中光标下的界面元素 / 内容块 / 窗口(悬停时轮廓高亮),随后 Enter 或双击才完成截取;什么都不点直接 Enter = 截取当前吸附到的目标。
- Space 关掉上面这套悬停吸附(高亮 + 单击选中),只剩自由框选;Tab 轮换 检测层级 自动(元素→内容块→整窗)→ 仅整窗 → 仅界面元素。两者只在未框选时 有效,每次重新截图自动复位。
- 框选完成后:拖动 8 个角/边手柄调整大小(自动出现放大镜);按住选区内拖动可整体 移动选区(已画标注跟着框走);鼠标移到选框外单击/拖动 = 自动扩选。
- 工具栏首位是选择 / 编辑:选了标注工具后框内变画图;换回它(不选具体 工具)即恢复框内拖动选区,点已画图形进入二次编辑。
- 截图历史 = 兜底:每次截图都进历史墙(托盘 → 截图历史),落盘在
%LOCALAPPDATA%\ZPin\history\(底图<id>.png+ 标注文档<id>.json+ 缩略图<id>.thumb.png),重启还在;默认保留 50 条 / 30 MB(设置 → 常规 可改), 缩略图时间戳到秒。一格五个动作:「贴图化 / 保存 / 复制 / 删除 / 清空」 (双击缩略图即贴图化)——保存直接写进默认目录,复制进剪贴板,删除/清空当场释放。- 「贴图化」把干净底图 + 标注文档一起贴上桌面,落在光标所在屏的中央 (连续贴图化按已有贴图数级联错开):画过的框还是活的,进标注模式能挪、 能改、能删,收工(完成 / 隐藏 / 关闭)自动写回这条历史,缩略图跟着变。 所以历史存的不是烘焙好的成品,而是这两样(不占双份空间)。
- 代价一处:马赛克/模糊的特效底图按「这张图」重新采样,重新合成的那一块与当初 复制出去的成品逐像素不完全相同(遮住的内容一样,格子相位可能不同);矢量形状 与智能擦除实测逐像素相同。
- 托盘「停用全局快捷键」:点一次禁用全部全局热键(托盘图标变为琥珀底、菜单文字变为 「启用全局快捷键」),再点恢复;状态持久化,重启后保持。
-
零隐式缩放:抓图画布 = 物理虚拟桌面,每屏按自己的原生像素 1:1 贴入, 缩放倍率恒为 1——混合 DPI 下副屏不会被上采样发糊。
-
裁剪逐字节无损:非整数逻辑坐标框选,成品与源图逐字节一致 (出现第 3 种颜色就意味着做了插值)。
-
标注按矢量几何直接烘焙在物理像素上,边带抗锯齿过渡,成品尺寸不变。 PNG / BMP / TIFF 与剪贴板全程无损(WEBP 质量拉满 100 也是无损;质量旋钮 只作用于 jpg / webp,其余格式没有这个概念);JPEG 默认质量 95 (实测整屏 PSNR 45.7dB, 体积仅 0.45MB,质量 75 只有 35.1dB 且文字边缘有彩噪;旧配置自动迁移)。
-
内存:每次截图完成后原图立刻交工作线程压成 PNG(1080p 整屏约 8MB → 0.7MB); 空闲 1 分钟后补压 + 裁剪工作集(可在 设置 → 常规 关闭)。马赛克底图首次使用才生成, 条数与字节双预算控制历史占用(默认 50 条 / 30 MB,设置 → 常规 可改)。
-
响应(原生版实测,release 构建):1080p 整屏高斯模糊 95ms(半径 30,单趟桥接); 抓屏稳态约 17ms/张(量的是 1536×864,测量进程未声明 DPI-aware 故被系统虚拟化, 真进程按原生分辨率抓,量级 25~30ms);UIA 单次取元素 3.3ms(每次重建 COM 对象是 3.9ms,故工作线程内缓存
IUIAutomation),查询走常驻吸附线程、选区交互线程 零 COM 等待;视觉内容块扫描(光标周围 800x800 物理 取景框)用一次性探针在 1920x1080@125% 真机上扫 437 个采样点:深色代码编辑器界面 中位 0.7ms、p90 2.5ms、最慢 3.5ms(其中 356 次光标落在空白上,1ms 内就放弃), 卡片密集的网页界面上中位 2.6ms、最慢 7.9ms(那轮还没省掉一次整框像素拷贝)。 三者都受 20ms 节流与「光标还在上次结果里就沿用」约束,不做无谓重复。 写盘与文字识别都在后台线程,主线程不阻塞。PP-OCR 选型实测(同一批图过 tiny / small 两档,det+rec+词典 5.99MB vs 29.67MB):用例 tiny 命中 small 命中 tiny small 浅底大字 900×260 4/4 4/4 70ms 139ms 深底扁条 1200×120 2/2 2/2 50ms 99ms 中英混排 760×300 4/4 4/4 60ms 138ms 12px 小字(含路径) 3/3 3/3 55ms 126ms 低对比浅灰字 2/2 2/2 45ms 86ms 密排长句 1/1 1/1 75ms 160ms 加噪截图 1/2 2/2 55ms 140ms 引擎加载 125ms 165ms 结论:small 慢 2.5 倍(中位 55ms → 139ms),换来的是噪声/低对比/小字 场景的明显更稳——加噪那张 tiny 把
2026-09-29认成了202?9-29、1,280.00丢了1,small 两项都对;小字那张 tiny 还把D:\Pictures\a.png吃成了D:Picturesla.png。识别是用户手动触发的后台动作,139ms 仍属无感, 故取 small。models/因此 6MB → 30MB(exe 体积不受影响:模型不进 exe)。 表格识别只再加一个版面模型 7.2MB → 37MB(行列网格由表格线检测 + OCR 框投影还原, 不需要结构模型)。 旧 Python 版的「截图链路约 40ms」没有对应的原生整链路测量,别照抄。
要求:Windows 10/11、MSVC 工具链(VS 2022/2026 均可)、CMake ≥ 3.24 与 Ninja
(VS 的可选组件,或 pip install cmake ninja 都行)、Qt 6.11.x(msvc2022_64 组件,
需含 QtSvg)、Rust 工具链(stable 即可)。
Rust 侧要从 crates.io 拉 cxx、oar-ocr + ort(ONNX 推理)与 image,
首次构建需要网络;PP-OCRv6 small 模型(det 9.4MB + rec 20.2MB + 词典 75KB)
与表格识别的版面模型(picodet_layout_1x_table 7.2MB)
已经放在项目的 assets/models/,构建期由 build.bat 拷到 exe 旁边的 models\,
运行时不联网、也不写到 %LOCALAPPDATA%。
另外还需要一份 OpenCV 静态库(智能擦除的修复算法,只用 core + imgproc):
下载 OpenCV 4.10.0 源码 zip
放到 build\opencv\opencv.zip,跑一次 tools\build_opencv.bat
(约 10–20 分钟,静态编进 exe、不加 DLL)。build\opencv\ 整个目录不进版本库;
没构建过 OpenCV 时 CMake configure 会明确报错指引到这一步。
build.bat rem 一键:配置 + 编译 + 收依赖
build.bat run rem 同上,完成后启动一次
build.bat zip rem 同上,再打一个发布 zip(自动更新的安装包)脚本顶部两个变量按本机改:VCVARS(vcvars64.bat 路径)与 QTDIR(Qt Kit 路径)。
产物在 dist\ZPin\:ZPin.exe(26.3 MB,内含静态链接的 ONNX Runtime)+ Qt DLL + 插件 + models\(37 MB)
- VC 运行时的散装 DLL(
vcruntime140*.dll/msvcp140*.dll,约 1.8 MB —— ZPin.exe 确实导入这几个,脚本从 VS 的 redist 目录直接拷过来,不再放vc_redist.x64.exe那个 18.7 MB 的安装包:装它就不叫「拷走即用」了)。 整个文件夹打包实测 112 MB。删掉结构模型不只省了 7.5 MB 模型,exe 也因不再链进结构推理的算子小了 3.9 MB —— 加/减模型都要把这两块一起算。 拷走即用(目标机不需要装 VC 运行时)。
只想编译不打包(开发期,产物在 build\zpin.exe):
tools\vsdev.bat cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=D:\Qt\6.11.3\msvc2022_64
tools\vsdev.bat cmake --build buildtools\vsdev.bat <命令> 就是「先进 MSVC 环境再执行命令」的包装器。
Rust 核心可单独编:cd rust && cargo build --release。
只有 Rust 核心带自动化测试(在 rust\ 下):
cargo test --releaseC++ 侧没有测试壳(本项目明确不引入),改动的验收方式是:cmake --build build
零警告零报错 → 跑 build.bat → 手动过一遍功能。必须手测才看得出的三类:
真实按键触发热键、贴图鼠标穿透、混合 DPI 双屏下贴图 1:1。
- 配置文件:
%LOCALAPPDATA%\ZPin\config.ini(启动时自动滚动备份为config.ini.bak) - 日志:同目录
zpin.log(启动分段计时、热键注册、未捕获异常都落在这里) - 开机自启:HKCU Run 键(不要求管理员);托盘「停用快捷键」状态同样持久化
- 与旧 Python 版共用同一份 config.ini 与键名,升级后原有设置直接沿用
CMakeLists.txt 一次 configure:Rust 静态库 + C++/Qt 可执行 + genico 图标工具
build.bat 一键打包(vcvars + cmake + windeployqt;build.bat zip 再打发布包)
cmake/genrc.cmake 构建期生成 zpin.rc(版本号 + 图标绝对路径)—— cmake\ 是脚本目录,
构建产物统一进 build\(CMake 与 cargo 同一个根,删掉即全量清理)
tools/vsdev.bat MSVC + Qt 开发环境包装器(vsdev.bat <命令>)
tools/genico.cpp 构建期把内嵌 SVG 渲染成 app_icon.ico(落在构建目录,不碰源码树)
tools/build_opencv.bat 一次性构建 OpenCV 静态库(build\opencv\,智能擦除依赖)
build/opencv/ OpenCV 源码与其构建产物(git 忽略;一次性,重建随时可跑上面那个脚本)
rust/ Rust 核心 crate(staticlib;blur capture content uia winrect ocr
ocr_layout table net stitch + cxx 桥)
cpp/ C++/Qt6 界面层,一个模块一件事,按领域分五个目录
(#include 一律平文件名,目录只是归档不是命名空间):
app/ 应用组装与共享业务服务:
main.cpp 进程入口(日志、单实例、QApplication 装配、启动分段计时)
app 装配层:创建并接线托盘/热键/选区/贴图/历史/设置/自动更新
tray ui_app_icon 托盘 / 应用图标(内嵌 SVG 现渲)
output history 保存输出 / 截图历史(落盘 + 双预算 + 后台压缩)
history_wall 截图历史墙:缩略图网格 + 贴图化 / 保存 / 复制 / 删除 / 清空
sys/ 系统交互与基础设施:
config defaults 配置读写与版本迁移 + 默认值唯一事实来源
logging win32util rcore 日志 / Win32 小调用 / Rust 桥
hotkey startup update memtrim 全局热键 / 开机自启 / 自动更新 / 空闲裁剪
capture/ 截图会话:
capture 多屏抓图:画布=物理虚拟桌面,每屏原生像素 1:1 + DesktopMap 换算
overlay overlay_paint 选区覆盖层 + 跨屏状态机 / 绘制实现
snap_worker scroll_capture 吸附工作线程 / 滚动长截图驱动
controller engine shapes 标注控制器/引擎/形状
toolbar text_edit ocr 工具条 / 原地文本 / 识别文字
smart_erase 智能擦除:PatchMatch 风格内容感知填充(OpenCV)
pin/ 贴图:pin_window pins pin_annotator(窗口/组管理/贴图上的标注交互)
prefs/ 设置与帮助:prefs_dialog prefs_pages key_edit prefs_icons help_page
assets/ zpin.rc(exe 版本信息与图标引用的模板,构建期展开到 build 目录)、
app_icon.ico(随仓库带的基线图标;构建期生成的那份落在 build 目录)
assets/models/ PP-OCRv6 small 的 det/rec ONNX + 词典,加表格用的 PicoDet 版面模型
(构建期随包拷到 exe 的 models\)
旧版目录结构是「根目录一堆 .py + PyInstaller」,Python 实现在原生移植完成后已整体删除; 要看旧实现请翻 git 历史(v1.2.0 及更早的提交)。
MIT © 2026 xinghui79
分发提示:运行时动态链接 Qt 6(LGPLv3),相比旧版 PyQt6 绑定不再触发 GPL 传染。 真要对外发布时需随包附 Qt 的 LICENSE 文本与源码获取地址——本机这套 Qt 是 aqtinstall 装的,安装目录里不带许可文本,所以
build.bat没有自动拷贝这一步。 仅本地自用不涉及分发,无需处理。Rust 核心与其依赖为 MIT / Apache-2.0; 智能擦除静态链接的 OpenCV(core + imgproc)为 Apache-2.0;assets/models/里的 PP-OCRv6 small 权重与词典、表格用的 PicoDet 版面模型 均来自 PaddleOCR / PaddleX 系(Apache-2.0), 下载时按oar-ocr内置登记表校验过 SHA-256。