Skip to content

Releases: ExpertKT/SnapWheel

v0.9.5 — 引导整理:那个【新】标记一直是假的

Choose a tag to compare

@ExpertKT ExpertKT released this 19 Sep 02:44

把「引导性质的东西」整个盘了一遍

起因是一个具体的错:引导里的【新】标记是假的。

原来的实现是一个写死的布尔量,贴在 7 条说明上(传递模式、贴图、取字、符号、界面语言、自动更新…)。
于是每次升级那 7 条都重新标一遍【新】 —— 升到 0.9.4,还在告诉你「传递模式」是新的,而那是 0.9.0 的东西。

标错的【新】比不标更糟:你会以为功能是刚加的,然后去找一个早就存在、早就该会的东西。

现在:每条说明都记着自己是什么版本加的,只有比你看过的那版更新的才标【新】。

你看过的版本 标【新】的条数
0.9.5 0
0.9.4 1(v0.9.5 新加的那条)
0.8.0 3(自动更新 / 传递模式 / 新增说明)
19(全部)

全新安装一条都不标 —— 对第一次来的人每一条都是新的,标满等于没标。

这 5 条已经是自动化测试里的断言,不是靠人眼看的。


为什么截图时微信会「突然消失」

这是很多人会撞上、但完全猜不到原因的事,已写进引导和 README:

微信给 Windows 设了「把我排除在截屏之外」SetWindowDisplayAffinity +
WDA_EXCLUDEFROMCAPTURE,Windows 10 2004 起的系统级机制)。

它的效果不是"拍成黑块",而是让抓屏透过去看到窗口后面的东西 ——
所以你按下截图热键、浮层盖住屏幕的那一刻,微信的位置显示的是它背后的桌面,看起来就是"微信咻地消失了"。

不是 SnapWheel 的问题,换任何截图工具都一样。

30 秒自助验证:按 Win+Shift+S(Windows 自带截图)框住微信 —— 同样拍不到,
那就说明是微信在反截屏。

顺手一提:SnapWheel 自己也给轮盘设了同一个标志,否则轮盘会拍进你截的每一张图里。
同一个机制,两边各用一次。

这不是推测,是量出来的。新增 tests/affinity-probe.cs,一条命令列出所有"反截屏"的窗口:

0x11  pid 59664  Weixin | Qt51514QWindowIcon | 微信   <== 从截屏里整个删掉
0x11  pid 57552  SnapWheel 快照轮环 | ...             <== 同一个机制(它自己故意设的)

还补了两条本来就该有的说明

删掉 / 撤回 / 退出:右键删除、托盘「撤销上一次删除」、关闭键长按 0.65 秒退出程序。

这三件事之前引导里一个字都没提,而删除还是单击右键即生效的 ——
相当于一个会丢数据的操作完全没有说明。


工程

  • 版本比较只留一份:更新检查要「远端比本地新吗」,引导要「这条说明比你看过的那版新吗」——
    现在统一到 AppInfo.IsNewer。两处各写一份迟早不一致。
  • ui-probe 测试以前只能手动跑,现在进了标准测试套件 —— 否则上面那 5 条【新】断言等于没写。

完整版 SnapWheel-v0.9.5-full.zip无万能键版 SnapWheel-v0.2.22-nokey.zip

绿色免安装,解压双击即可,零第三方依赖。

v0.9.4 — 修掉「自动更新永远不会生效」

Choose a tag to compare

@ExpertKT ExpertKT released this 17 Sep 03:50

⚠️ 请手动下载,不要等自动更新

v0.8.1 ~ v0.9.3 的自动更新是坏的 —— 这个版本修的就是它本身,所以老版本收不到推送。
如果你在用老版本,请直接下载下面的 zip。


修掉「自动更新永远不会生效」

现象:托盘 →「检查更新」→ 下载完成 →「现在重启并安装?」→ 点「是」→ 程序重启 → 版本号一点没变

根因:更新器模式的入口被注释吞掉了。

v0.8.1 给 Main 插入了这一行:

if (Update.IsApplyMode(args)) { Update.RunApply(args); return; }

但插入时它被挤进了同一行前面那段注释里,于是整行都成了注释。
Update.IsApplyMode / Update.RunApply92-Update.cs 里定义得好好的,
却从来没有任何地方调用它们 —— 点了「是」之后启动的那个进程,走的还是普通启动流程。

为什么几个月都没被发现

这个 bug 把所有常规信号都躲过去了:

信号 为什么没报警
编译 通过 —— 注释本来就是合法的
警告 0 条
测试 全绿 —— 当时只测了「版本比较」和「ZIP 解压」,没人测入口
README 「自动更新」写得漂漂亮亮,功能看着齐全
日志 一切正常,因为根本没走进那条分支

它不是跑出来的,是逐行读代码读出来的。 Main 开头那行长得不对劲 ——
一行注释里塞了两个 // 和一段大括号。

新增守卫:tools/check-swallowed.ps1

这类 bug 编译器、警告、测试、CI 全都看不见。只有读能发现 ——
那就把「读」里能机械化的那部分交给机器:扫描纯注释行里出现完整块语句的形状。

判据是实测调出来的:先用事故原文验证它确实命中,再扫全仓库确认 0 误报。
中途试过「注释以分号结尾」这条更宽的判据,实测误报 5 处(文档注释里贴代码示例很正常),已弃用。
已接进构建流程。

测试不再「看运气」

修图标时发现测试套件是抖动的:同一份代码连跑三次,绘制测试报 3 / 2 / 1 个 FAIL。
「测试全绿」这句话当天骗了我们两次,所以这次治根 —— 三条抖动测试全改成确定性断言:

测试 原来为什么抖 现在怎么测
启动时把手渐显 隔 150ms 采样后断言像素数严格递增;动画一旦短于采样间隔,「中途」恰好等于「结束」 把动画进度直接拨到 0 / 0.5 / 1 再看画面。断言也更强:必须真的经过中间态
换背景有淡入过渡 Sleep(120) 抓两帧比差异 —— 而且差异算出来根本没参与断言 种两张颜色明确的底,验证 fade=0.5 时像素恰好是两个端点的中点
展开/收起耗时对称 在共享机器上量真实墙钟,却用 1.3 的死阈值 各测两次取较快者抵消卡顿;阈值放到 1.4 容纳噪声

顺带发现:BackdropMix()按帧号缓存的(同一帧只混一次,这是性能设计),
测试直接调 DrawWheel 会绕过自增帧号的 RenderCore —— 不手动推进帧号,读到的一直是同一张缓存图。


完整版 SnapWheel-v0.9.4-full.zip无万能键版 SnapWheel-v0.2.22-nokey.zip

绿色免安装,解压双击即可,零第三方依赖。

v0.9.3 — 工具条图标修复与收尾

Choose a tag to compare

@ExpertKT ExpertKT released this 16 Sep 07:13

这一版不加新功能,只做收尾修复 —— 目标是进「稳定期」前的最后一轮打磨。

修掉的东西

标注工具条的 A- / A+ 图标
字母 A 原来"撑满按钮 + 居中",而减号/加号画在按钮右侧,两者压在一起。现在 A 只占左边 3/4。

标注工具条的撤销图标(换了两轮字符才确定不能用字符)

  • (U+21B6):弧线天生只占半格、字号偏小,看着就不对劲;
  • (U+27F2):先在候选对照图里挑了它(5 个字符 × 3 字体 × 3 字号),24pt 下是漂亮的圆环 + 箭头
    但按钮里只有 17pt,字形被 hinting 简化成"半圆 + 一竖",用户看到的仍然是异常。

结论:小字号下不该依赖字体字形。改为手绘「开口圆环 + 向左的实心三角箭头」,
半径写死 8*k,和旁边笑脸、另存为保持同一个量级。

工具条文字发虚T / A / 是白字深底,ClearType 的彩色次像素边会渲染出红蓝描边,
放大看像"字歪了、有重影"。工具条内改用灰度抗锯齿。

长图图标顶出按钮框 — 上下箭头原来画到 ±14,而按钮内高只有约 26px。

绘制层一个"整行不画"的隐藏 bug — 框高比字体实际高度小 1.2px 时,
Graphics.DrawString 既不裁切也不缩小,而是什么都不画。已用 Font.Height + 2 兜住,
并补了 6 字号 × 6 框高的回归测试。

体验

  • Esc 取消传递时,缩略图飞回环上(缓动 + 淡出 + 缩小,320ms),不再瞬间消失。

工程

  • 新增 tests/toolbar-zoom.cs:把工具条裁出来放大 6 倍出 PNG。
    按钮只有 34×30 像素,在整屏图里根本看不清图标 —— 之前两轮"图标异常"都是靠肉眼猜的,一次也没看准。
  • 新增 tests/ui-probe.cs:子控件矩形统一换算到窗口坐标系后两两求交,专测控件重叠。
  • 修掉测试里的假 FAIL:断言写死的"工具条 14 个按钮"改成读源码常量。

完整版 SnapWheel-v0.9.3-full.zip无万能键版(多轮盘 + 框选缩放/锁定)SnapWheel-v0.2.22-nokey.zip

绿色免安装,解压双击即可,零第三方依赖。

v0.9.2 — 修传递模式放下没反应

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 16:30

v0.9.2

修掉传递模式"放下没反应"

现象一直是同一个:按空格之后鼠标从起点移到终点,然后什么都没发生,换任何参数都一样

根因:SetCursorPos 只把光标"瞬移"过去,不产生鼠标移动消息。而轮盘的拖出是靠「按下 + 鼠标移动」启动的(OLE 拖放 DoDragDrop 的启动条件)—— 收不到移动消息,DoDragDrop 永远不会被调用。

修法:移动光标时补发一个 MOUSEEVENTF_MOVE

这个修复曾经写对过一次(当时反馈"重新截一张图就能用了"),但后来做代码回退时被一起退掉了 —— 于是之后无论怎么改坐标、步数、时序、DPI,都必然得到同一个失败现象。现在这段加了显眼注释防止再丢。

顺带修的

  • 起点可能落在屏幕外:轮盘贴屏幕底部时,缩略图中心会超出虚拟屏幕(实测 Y=1199 而屏幕高 1152),SetCursorPos 把光标夹到边缘,按下就落在空白处。现在取缩略图矩形与屏幕的交集中心
  • 图取不到内容时明确提示,不再默默无反应。
  • 传递模式加了诊断日志(是否被调用 / 轮盘项数 / 起点坐标 / 实际光标位置)。

下载

  • SnapWheel-v0.9.2-full.zip — 完整版(含万能键)
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

v0.9.1 — 修新手引导(遮挡 / 过长 / 首次限制失效)

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 16:18

v0.9.1

只修 v0.9.0 里新手引导的三个问题:

  • 内容被「开始使用」按钮遮住 —— 滚动是靠移动控件位置实现的,而 WinForms 的窗体不裁剪子控件,超出窗口的内容照样画出来,于是有个标签正好压在按钮上。现在滚动内容放进一个 Panel(它会裁剪子控件),滚到边界就被切断。
  • 窗口太长 —— 高度上限原来是「屏幕高度 − 24px」,内容一多就顶满整屏。现在收到屏幕的 72%,内容超出靠滚轮翻看。
  • 「首次安装只显示 3 条」没生效、设置里的说明反而被截断 —— 判断条件用错了(拿 markNew 当"是否首次")。现在改用独立的 brief 参数:只有首次安装才只给 3 条,设置里和升级提示都完整显示。

三种引导(设置里 / 首次 / 升级)都用离线探针实测过:与按钮重叠 = 0

下载

  • SnapWheel-v0.9.1-full.zip — 完整版(含万能键)
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

v0.9.0 — 传递模式(不用鼠标也能把图送出去)+ 引导改版 + 自动更新

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 15:59

v0.9.0

新功能:传递模式(不用鼠标也能把图送出去)

Ctrl+Alt+C,屏幕上出现一个「假光标」,右下角吸附着当前选中的缩略图。自己 Alt+Tab 切到目标窗口,把它移过去,按空格放下 —— 它会真的替你完成一次鼠标拖放,所以任何支持拖放的窗口都能用。

作用
方向键(或 WASD) 移动假光标
Shift 加速
空格 / Enter 放下
[ ] 换一张
C 只复制到剪贴板(不自动粘贴)
Esc 取消

移动推荐用方向键、换图用方括号 —— 它们不产生文字,不会在目标窗口里留下字母、也不会把输入法叫出来。

热键被占用时会自动换备选(Ctrl+Alt+W / F9 / F10),托盘菜单上显示当前实际生效的那个。

引导改版

  • 首次安装只显示 3 条(三步上手),不再一上来丢一长串没人看
  • 设置里的说明补全到 20 条:新增传递模式、取字 OCR、滚动长截图、另存为与单击复制、符号标注、界面语言、自动更新
  • 跟着版本走:升级后自动弹「这次多了什么」,新增条目带【新】标记

自动更新(不花一分钱

托盘 →「检查更新」→ 下载 → 自动替换并重启,轮盘和设置都保留。不需要服务器、不需要代码签名。

修掉的重要问题

  • 模拟拖放一直不成功 —— 根因是轮盘是不激活窗口,而 Windows 会把「非活动窗口的第一次点击」用来激活它、应用收不到,模拟点击被系统吃掉,OLE 拖放永远不会启动(所以之前无论怎么调参数都是同一个效果)。现在放下前先把轮盘拉到前台。
  • 图取不到内容时明确提示,不再默默什么都不做。
  • 传递模式刚进入时窗口一闪就关 —— 手指还压在热键上,被当成"用户操作"了;现在一次性动作键用上升沿判断 + 350ms 保护期。

下载

  • SnapWheel-v0.9.0-full.zip — 完整版(含万能键)
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

v0.8.0 — 工程重构(绘制度量层/拆大文件/i18n自检)+ 自动更新

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 12:43

v0.8.0

这一版没加新功能,做的是工程上的三件事(避免项目变成没人敢改的"屎山"),外加一个自动更新

一、绘制度量层 DrawKit

项目里同一个错误犯过四次:测量用一套参数、绘制用另一套 → 文字被裁、框和图形错位、预览正常但导出跑偏。
根子不是"写错了",而是约定没有被强制

新层把「量」的结果封装成 Fit 值(字体、字号、样式都在里面),画的时候只接受它 —— 调用方拿不到单独的字号,也就没法"另起一套"去画。错误在结构上写不出来。

配套 tests/drawkit-test.cs(项目第一套像素级自动化测试,6/6 通过),当场逼出两个没预料到的问题:字号与宽度不是线性关系(改迭代缩小)、缩到下限仍放不下时会一直溢出(改逐字截断加省略号)。

同时全线改用 GDI+:实测 GDI 的 DrawText 在 2560×1440 画布上单次 9.2ms(小画布 0.43ms,差 21 倍)。

二、拆大文件

文件 拆前 拆后
75-SettingsForm.cs 1607 1057
61-WheelForm.Draw.cs 1205 357
51-OverlayForm.Annotate.cs 1194 616
50-OverlayForm.cs 1000 763
64-WheelForm.Input.cs 769 593

每一处都用同一个标准验证:拆完编译,exe 大小与拆分前完全一致(322,048 字节)—— 证明是纯搬移、零行为变化。

三、多语言自检脚本

tools/check-i18n.ps1:扫漏翻、扫"同一个中文配了不同英文"(翻译漂移)、扫长度异常。实测 395 条全部健康。

四、自动更新(不花一分钱

不需要服务器、不需要代码签名、不需要任何付费账号。

检查(匿名读 GitHub Releases,限流 60 次/小时够用)→ 下载到临时目录 → 用 --apply-update 启动"更新器模式"的自己:等主进程退出 → 覆盖文件 → 重新拉起主程序 → 自己退出。

升级是覆盖已有文件,不触发 SmartScreen。托盘菜单新增「检查更新」,设置里保留开关(启动时静默检查,只在新版时提一句)。
自己实现了 ZIP 解压兜底(DeflateStream)—— 因为编译目标是 .NET 4.0,反射调不到系统解压组件,这个坑是测试发现的。

下载

  • SnapWheel-v0.8.0-full.zip — 完整版(含万能键)
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

v0.7.1 — 比例动画性能修复(9倍)+ 层级焦点回归 + 界面语言

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 12:09

v0.7.1

性能:比例面板动画卡顿修掉了(该段 9 倍)

把一帧拆开逐个函数计时,发现比例胶囊的绘制占 8.2ms(一帧总共 16.4ms)。

真凶:TextRenderer.DrawText(GDI)在 2560×1440 的目标位图上单次要 9.2ms,而同样操作在小位图上只要 0.43ms —— 相差 21 倍。因为 GDI 的 DrawText 会沿整个目标表面处理裁剪区域,目标越大越慢;GDI+ 与目标大小无关。改用 DrawString 后该段 8.21ms → 0.91ms,全屏重绘 16.4ms → 5.9ms(约 166fps)

完整的排查过程(含三轮错误猜测与实测数据对比)写进了 docs/LEARNING.md §2.4

层级与焦点(回归修复)

  • 修复「打开设置窗口,设置跑到主窗口下面」(上一版引入:只抑制了周期置顶,忘了轮盘本来就在顶层)
  • 截图浮层显示后主动抢前台
  • 轮盘在弹框/截图期间的置顶改用抑制计数,嵌套时不再丢状态

比例胶囊

  • 未框选时不显示(原来按展开后总宽居中,收起时按钮偏左)
  • 展开时与工具栏重叠会自动往下让开
  • 收起时文字有渐隐过渡(原来 GDI 不认半透明,字是突然消失)

界面语言

新增「界面语言」设置项(跟随系统 / 中文 / English),380+ 条文案接入(托盘、设置窗口、对话框、截图浮层、取字窗口、长截图提示、反馈窗口…)。

其它修复

尺寸面板闪烁(双缓冲 Panel)、英文长句溢出(10 条改为两行)、拖出缩略图后不再从环上移除、系统版本读取改注册表、长截图避开任务栏、删除后视口平滑跟进。

下载

  • SnapWheel-v0.7.1-full.zip — 完整版(含万能键)
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

v0.7.0 — 符号标注(可选颜色)+ 另存为 + 界面语言

Choose a tag to compare

@ExpertKT ExpertKT released this 15 Sep 09:08

v0.7.0

截图浮层新增两个工具

符号标注 —— 工具条上的符号按钮 → 弹出面板,顶部可选颜色(红/黄/蓝/黑,与标注色一致),下面三组共 72 个矢量符号:标记(✓ ★ ♥ ● ▲ ◆ …)、箭头(→ ⇒ ↻ …)、编号/其它(① ~ ⑫ ✎ ✂ ☎ …)。插入后和箭头、文字一样是标注元素:可拖动、滚轮/按钮改大小、Del 删除、Ctrl+Z 撤销,确认时合成进图。字体自带的矢量符号,单色可上色、放大不糊。

为什么不是 emoji:Windows 的彩色 emoji 靠 Segoe UI Emoji 的 COLR/CPAL 表,而 .NET Framework 的整条文本栈都不读这两张表 —— GDI、GDI+、WPF FormattedText、WPF TextBlock 四条路实测全是黑色剪影(做过像素分析确认)。真彩色只能上 Direct2D 的 COM 互操作,对这个"单 exe、零依赖"的项目代价不成比例。所以改用矢量符号,并因此回归零依赖

另存为 —— 把当前框选(含标注)存到你选的位置,系统保存对话框,格式按扩展名走(PNG / JPEG / BMP,JPEG 自动铺白底避免透明变黑)。存完之后这张仍留在轮盘里,方便继续拖出去用。

界面语言(第一轮 i18n)

  • 设置 → 行为 → 界面语言跟随系统 / 中文 / English,切换后重启生效
  • 默认跟随系统语言,也可以显式指定后固定
  • 第一轮已接入:托盘菜单全部 14 项
  • 实现方式是 Lang.T("中文", "English") 就地双写,不做 key 字典 —— 漏翻一眼能看见

修掉的问题

  • 拖出缩略图后不再从环上移除:拖出是 Copy 语义,以前当成 Move,导致"拖一次就没了、不能再拖"。现在默认留一份,可在设置第 1 页关掉
  • 轮盘置顶不再抢焦点(改用 SetWindowPos + SWP_NOACTIVATE):以前每 2 秒用 TopMost 重设会抢一次前台焦点,导致托盘右键菜单和打赏窗口"点出来过一会儿自己关了"
  • 反馈里的系统版本改读注册表(以前固定报 Windows NT 6.2 = Win8)
  • 长截图:拼接时避开屏幕底部静止区(任务栏不再被一路重复贴进长图);自动滚改成一格一格,重叠区更大才拼得上
  • 缩略图删除后视口平滑跟进;滚动范围放开到最后一张;计数序号改成"弧下端那一张"
  • 大图缩略图的放大动画首次不再卡

下载

  • SnapWheel-v0.7.0-full.zip — 完整版(含万能键),解压即用
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

两条产品线都编译 0 警告,只有一个 exe,不需要安装。

v0.6.0 — 滚动长截图 + 翻译引擎链 + 取字更准 + 弧线设计语言

Choose a tag to compare

@ExpertKT ExpertKT released this 14 Sep 15:49

这一版四件事

1. 滚动长截图(自动滚) —— 截图浮层里框一块区域 → 点工具条上的长图按钮 → 程序自己滚、自己按重叠区无缝拼接,到底自动停。拼不上时会明确说原因,绝不硬拼出错位的接缝。

2. 翻译换引擎链 —— 原来只有 MyMemory(机翻腔重)。现在:自填的 OpenAI 兼容接口(DeepSeek / 豆包 / 通义 / 本地 Ollama 都行)→ 有道免费接口(无 key、国内直连,默认走这层)→ MyMemory 保底。

3. 取字更准 —— 低对比度截图(暗色主题、浅灰字)先做直方图拉伸再识别:实测同一张图从 0% 认出提升到 92%~97%;普通 14px 正文 82.9% → 87.8%。

4. 弧线设计语言 —— 三个小按钮紧贴万能键左上方沿弧排布、悬停时按主题色发光;计数胶囊沿弧弯、数字顺着弧排。

另外:所有对话框在 150% DPI 下不再裁字、大图缩略图的放大动画首次也不再卡、删中间一张图时上面的图会平滑滑下来填补空位。

下载

  • SnapWheel-v0.6.0-full.zip — 完整版(含万能键),解压即用
  • SnapWheel-v0.2.22-nokey.zip — 无万能键版

两条产品线都编译 0 警告,只有一个 exe,不需要安装。