Skip to content

WindowMark v0.5.0 — 窗口拖动

Choose a tag to compare

@yakoye yakoye released this 11 Sep 02:16
· 36 commits to main since this release

窗口拖动

按住修饰键(默认右 Alt),在窗口内的任意位置按下鼠标就能拖它 —— 不用够到标题栏,也不用瞄准四条边。

主要解决一件事:窗口跑到屏幕外面,只剩一个角还露着。这时候标题栏和拖动区都在屏幕之外,鼠标根本点不到,窗口就再也拉不回来了。

手势 行为
修饰键 + 左键拖 整窗移动,窗口内任意位置
修饰键 + 左键单击 窗口居中到光标所在那块屏(位移 4px 以内算单击)
修饰键 + 右键拖 缩放,按下位置落在九宫格哪一格决定拉动哪几条边

默认关闭。托盘 →「窗口拖动」→「启用」。触发键六个预设可多选(左右 Ctrl / Alt / Win),默认只勾右 Alt —— 左 Alt + 拖动被 Photoshop、IDE、Blender 占着,装在左 Alt 上会吞掉那些操作。

单击居中不占任何额外按键:那次按下本来就被拖动吞掉了,应用永远收不到,不接上就是白白浪费。

两个踩过的坑

移动事件不能吞。 WH_MOUSE_LL 返回非零 = 事件不再往下走,对移动来说就是光标不动。真实鼠标报的是相对位移,系统拿「当前光标位置 + 这一跳的位移」算 MSLLHOOKSTRUCT::pt —— 光标被钉死,pt 就永远只在按下点附近晃一个鼠标 tick 的距离,永不累加,表现是「窗口只晃一下就不动了」。

这个 bug 躲过了原来那份合成测试,因为它注入的是绝对坐标:pt 不依赖当前光标位置,照样累加,测试完全绿。改成相对位移注入后,同一份测试立刻抓住了它。判据也跟着改成「窗口位移 == 光标真实位移」,并单独断言光标确实动了 —— 少了这一条,「窗口没动 + 光标也没动」会当成两者一致蒙混过关,而那恰恰就是这个 bug 的样子。

鼠标底下不能拖时,要往 z 序下面找。 系统会留下看不见却铺满整块屏的 topmost 窗口:锁屏的 Windows.UI.Core.CoreWindow(LockApp.exe)和 LockScreenInputOcclusionFrame,解锁之后有时并不消失,IsWindowVisible 仍然是 1。TargetWindowAt 原来只问一次 WindowFromPoint,拿到不能拖的就返回空,于是整个手势在那块屏上彻底失效,而屏幕上什么异常都看不出来。现在继续往下找第一个能拖、且盖住这个点的窗口;只在按下时走一次,不进移动的热路径。

性能

空闲路径只有两行:先看在不在拖动,再看修饰键按没按(GetAsyncKeyState,几十纳秒),不查窗口、不算几何、不碰配置。装与不装钩子的差值落在噪声里。

键盘钩子只在配置含 Win 键时才装 —— 单独按一下 Win 再松开会弹出开始菜单,要压掉被手势用掉的那一次抬起只能靠 WH_KEYBOARD_LL;它比鼠标钩子更敏感,不该让所有人默认承担。


安装:下载 WindowMark-v0.5.0-win64.zip,解压后运行 WindowMarkSetup.exe。不想安装就直接跑解压目录里的 WindowMark.exe。升级会保留现有配置。

完整变更见 CHANGELOG.md。