Releases: informalgit/AppHopper
Release list
v1.1.1 — 切回游戏聚焦修复 + 版本号嵌入
v1.1.1 修复
从其他窗口(如终端)切回英雄联盟窗口需按两次 Alt+Tab 的问题。
根因
ForceForeground 的慢路径 3 次重试在 6ms 内打完(无 sleep、无 attach),但游戏激活是异步的(实测落地耗时 19-110ms)。SFW(游戏) 发出后系统进入前台切换中间态,GetForegroundWindow() 返回 0。旧代码把 fg==0 误判为「无人持有焦点」,立即执行兜底 SetForegroundWindow(源窗口),亲手取消了自己刚发出的激活。4 次重试 4 次失败,形态完全一致。
修复
- WaitForForegroundLanding:Commit 失败后先等最多 300ms(10ms 分块 Sleep + DoEvents),轮询复核。触发条件:fg 变为目标即成功;若连续约 30ms 被外来窗口稳定持有才提前放弃(去抖),之后走原兜底逻辑(失败路径语义不变,不再抢跑撤销在途激活)。
- 慢路径真等待:每轮迭代末尾
Sleep(15),迭代 3→8 次,200ms 墙钟上限不变。 - attach 目标线程:fg==0 时不再静默跳过 attach,改为 attach 目标窗口的线程(任务栏经典做法,v1.0.5 遗留机制,本次补回)。
WM_APP_START守卫:等待期间泵消息且_session==false,不加守卫 Alt+Tab 会开新会话被在途 Commit 拆掉。加!_committing守卫丢弃按键。
快路径(普通窗口切换)零改动,行为不变。
版本号嵌入(A+C 方案)
- 文件头三行
assemblyattribute:AssemblyVersion("1.1.1.0")/AssemblyFileVersion("1.1.1.0")/AssemblyInformationalVersion("1.1.1")。盒装 csc 自动编入 PE 的 VS_VERSIONINFO,Explorer 右键属性 → 详细信息可见,build.bat零改动。 - 运行时
AppVersion字段从 InformationalVersion 读回(兼容 .NET 4.x 旧 API)。 - 托盘悬停显示
AppHopper 1.1.1,--log首行写AppHopper v1.1.1 starting, pid N。 - 以后发版只改文件头这三行;本地 exe 文件名保持固定(
SetStartup用Application.ExecutablePath写 Run 键,文件名带版本会导致升级后自启动静默失效)。发 Release 时上传资产改名AppHopper-1.1.1.exe即可。
v1.1.0 备注
v1.1.0(改名发布)此前只推了 tag,未建 GitHub Release;本次一并补上。
验证
本地 exe 未重新编译(仍为 15:04 构建)。用户需:托盘退出旧 exe → 双击 build.bat → 验证属性 / 悬停 / 日志 / 切回游戏行为。沙箱禁 csc,编译由用户执行。
v1.1.0 — 项目改名为 AppHopper
项目改名为 AppHopper——"在应用之间跳",功能与代码逻辑不变。
改名
AltTabSwitcher→ AppHopper:exe(AppHopper.exe)、源文件(AppHopper.cs)、命名空间、托盘提示、日志文件(apphopper.log)全部随之更新;GitHub 仓库同步改名为 informalgit/AppHopper。- 自启动注册表键名从
AltTabSwitcher改为AppHopper;单实例 Mutex 名也一并更新。
升级注意
- 如果开启过 Start with Windows:注册表里旧的
AltTabSwitcher启动项不会自动迁移,且指向已不存在的旧 exe——请删掉它,再在新版托盘菜单里重新勾选一次 Start with Windows。 - Mutex 换了名字,旧实例不再能挡住新实例,升级前先从托盘退出旧版。
- 切换器本体、快捷键、UI 与 v1.0.7 完全一致(v1.0.7 的 release notes)。
说明
- 构建:双击
build.bat(用 .NET Framework 的 csc)。
v1.0.7 — 背景宽度跟随窗口数量
v1.0.6 的回归修复:切换条背景宽度不再定死。
修复
- 背景宽度跟随窗口数量。v1.0.6 改换行逻辑时写死了列数上限,导致不管几个窗口,白色面板都按 6 格宽铺 —— 只有 2 个窗口时两边会留出大片白边。
现在面板宽度取实际用到的最宽一行,2 个窗口就是 2 格宽(630px),3 个 926px,6 个及以上才是 1814px。
验证方式
改的是纯布局计算,因此把 v1.0.5 与本次的 ComputeLayout / TileRect 分别移植成同一份 Python 实现做差分对照,
扫 3 种工作区尺寸 × 1~24 个条目、逐格比对坐标与面板尺寸:
- 面板宽高与 v1.0.5 完全一致(0 差异)
- 唯一的行为差异就是想要的那一处:短的最后一行居中,而不是左对齐
说明
- 构建:双击
build.bat(用 .NET Framework 的 csc)。旧进程提权后 taskkill 杀不动,先托盘退出再编译。 - v1.0.6 的完整改动(切出资源管理器不再滞留、最小化窗口也有缩略图、末行居中、会话中关窗口实时重排、开场更快)见
v1.0.6 的 release notes。
v1.0.6 — 切换条不再滞留、最小化窗口也有缩略图、末行居中
修复
- 切换条不再滞留。
AttachThreadInput是同步跨线程调用,要等对方线程处理,而 Explorer 的窗口线程正是可能忙几百毫秒的那种;浮层又是在激活完成之后才隐藏的 —— 这就是"从文件资源管理器切出时切换条挂一下、快速来回切换更明显"的原因。
现在快路径完全不 attach(F24 输入声明已经足够授权SetForegroundWindow);只有快路径失败才进慢路径,且进入慢路径前先把浮层收掉,并限时 3 次 / 200 ms。 - 顺带修掉一个回弹 bug:旧的重试循环在
BringWindowToTop一次就成功时会误判为失败,进而把前台还给源窗口(就是"To Do 又跑回前面"那类现象)。 - 最小化窗口也有缩略图。实测 DWM 对最小化窗口照常提供缩略图,保留的正是最后一次呈现的画面(报的是还原尺寸)。之前代码主动跳过了最小化窗口,而这台机器大半窗口是最小化的,所以满屏空白格。现在只跳过 cloaked(其他虚拟桌面 / 应用自行隐藏),源尺寸退化时也不再拉伸出一整块空白。
- 看门狗 100 ms → 30 ms(Alt 抬起到浮层消失的最坏延迟);浮层窗口加
SWP_NOACTIVATE,永不抢前台。
改进
- 换行改为「填满一行再换行」,并且每一行居中:短的最后一行居中摆放,不再出现右侧一整片空白。
- 切换条开着时关掉窗口会实时重排:按 exe 键归并,幸存条目保持原来的位置,重新布局 / 重注册缩略图 / 重绘;没有任何窗口可切换时静默结束会话。
- 打开切换条更快:图标按 exe 缓存(原来是每条目最多两次
WM_GETICON,每次带 100 ms 超时跨进程往返),exe 路径在同一次枚举内记忆化。
说明
- 本版本同时包含 v1.0.5(此前只推了 tag、没发 release)的内容:带
WS_EX_APPWINDOW的窗口(资源管理器属性 / 另存为 / 偏好设置对话框等)在切换条中独立成条,不再被所属 exe 的条目吞并 —— 否则这类对话框永远切不过去。 - 构建:双击
build.bat(用 .NET Framework 的 csc)。旧进程提权后 taskkill 杀不动,先托盘退出再编译。
v1.0.4
Alt+Tab 应用切换器 v1.0.4。
二进制见下方 Assets 中的 AltTabSwitcher.exe(启动即申请管理员权限);源码用户请 clone 后执行 build.bat 自行构建(exe 与 log 不入库)。
主要变更
- 修复双重 commit 竞态:
Application.DoEvents()会把第二个提交触发(watchdog tick / 排队的WM_APP_COMMIT)泵成嵌套Commit;内层激活目标、结束会话后,外层继续重试并失败,最终把前台还给源窗口(表现为"Microsoft To Do 一直前置")。现已加入重入守卫与幂等收尾,Commit入口先解除全部会话级触发源。 - 失败兜底改为三分支:只有当前台丢失(
0x0)或停留在自身浮层时才归还源窗口,绝不从第三方持有者手里抢回前台。 - 日志调用移出低级键盘钩子回调(
LowLevelHooksTimeout会静默移除执行 I/O 的钩子),改在消息处理处记录热键链路。 - 窗口合格性判定合并为单一
AltTabIneligibilityReason(同时服务过滤与日志,避免两份逻辑漂移),owner 链遍历抽为OwnerChainRepresentative。 - 文件内结构拆分:
NativeMethods(P/Invoke、常量、结构体、COM)、Logic(纯布局与排序逻辑,对应 PowerToysAltWindowCycleLogic.h)、AppEntry提升到命名空间级。 - 构建:
build.bat嵌入app.manifest,声明requireAdministrator与PerMonitorV2DPI 感知。
运行要求
- 需以管理员权限运行:当前台窗口属于提权进程时,线程附加、前台激活以及读取其 exe 名与图标都需要提权。
- 编译前请先从托盘退出正在运行的实例(或右键以管理员身份运行
build.bat):提权后的实例无法被普通命令行的taskkill结束,否则输出文件被占用会导致编译失败。
已知问题
- 切换到 UWP 目标(如 Microsoft To Do)的激活仍在排查中。
- 单应用时按键被吞但无响应、最小化窗口的恢复为已知待办项。
English
Alt+Tab application switcher v1.0.4. Download AltTabSwitcher.exe from Assets (requests elevation on launch); to build from source, clone the repository and run build.bat (exe and log files are intentionally not tracked).
Changes
- Fixed the double-commit race.
Application.DoEvents()pumped a second commit trigger (watchdog tick or queuedWM_APP_COMMIT) into a nestedCommit; the inner one activated the target and ended the session, while the outer one kept retrying, failed, and handed the foreground back to the source window ("Microsoft To Do stays in front"). Added a reentrancy guard plus idempotent teardown;Commitnow disarms every session-scoped trigger before doing any work. - Three-branch failure fallback. The source window is restored only when the foreground is lost (
NULL) or held by our own overlay — never yanked from a foreign holder. - Logging moved out of the low-level keyboard hook callback (
LowLevelHooksTimeoutsilently removes hooks that perform I/O). - Single window-eligibility predicate (
AltTabIneligibilityReason) serving both filtering and logging; owner-chain walk extracted toOwnerChainRepresentative. - In-file structural split:
NativeMethods,Logic(pure layout/cycle math mirroring PowerToysAltWindowCycleLogic.h),AppEntry. - Build:
build.batnow embedsapp.manifest(requireAdministrator, PerMonitorV2 DPI awareness).
Requirements
- Must run elevated: attaching to, activating, and querying windows owned by elevated processes all require admin rights.
- Exit the running instance from the tray before rebuilding (or run
build.batas administrator) —taskkillfrom a non-elevated shell cannot terminate an elevated instance, and the locked output file breaks the build.
Known issues
- Activating a UWP target (e.g. Microsoft To Do) is still under investigation.
- Key swallowed without response when only one application is running, and restoring minimized windows, remain open items.
v1.0.3 — 窗口枚举与会话生命周期加固
排查与加固(本轮系统性排查枚举/判定/会话管线)
- 补全原生 owner 链判定:改用经典的 Alt-Tab 代表窗口判定(根 owner → GetLastActivePopup 链式回溯)。修复:主窗口最小化但它的可见对话框还开着时,这一组此前会被漏掉,现在与原生一致。
- 排除桌面窗口:点击桌面后,桌面窗口(Progman/WorkerW)可能成为 explorer 组的代表,导致 Alt+Tab "切到桌面";现已排除。
- 排除系统输入体验窗口:对 "Windows Input Experience" 增加标题过滤(与 DWM 斗篷过滤互补)。
- 会话健壮性:Alt 松开事件若被系统丢弃,100ms 看门狗会自动落窗,切换器不可能卡在屏幕上吞掉点击;切换目标窗口若在会话期间被关闭,现在直接跳过而不会报错。
以上均为行为加固,已用真实桌面环境回归验证(应用集合与顺序与修复前完全一致)。
SHA256: f092dcd806c0701ce7f22f6d719e0404440fa2137fe9f98aa39f62ea4d6fb496
v1.0.2 — 隐藏的系统窗口不再混进 Alt+Tab
修复
- 隐藏的系统窗口不再混进 Alt+Tab 列表:此前"Microsoft Text Input Application"(输入法宿主 TextInputHost.exe,一块全屏的隐形窗口)以及处于挂起状态的 UWP 应用会出现在切换列表里。原因:这类窗口逻辑上"可见"但被 DWM 斗篷(cloak)隐身,原生切换器会排除它们,而本工具在上一次 UI 移植时把这个检查弄丢了。现已恢复与原生一致的行为。
- 同一修复也覆盖其他披斗篷窗口(如挂起的系统宿主),列表现在只显示你真正看得到的应用。
说明
Alt+Tab在应用之间切换(每个应用一个条目,macOS Cmd+Tab 风格);应用内窗口切换(如 PowerToys Window Hopper)继续使用各自的快捷键,二者完全分离。- 下载
AltTabSwitcher.exe双击运行即可(免安装),托盘图标可设开机自启。适用于 Windows 10/11 64 位。
SHA256: de92ad186a47b56800887c209be872c350a12250e4e2221ae7b661cec67efb26
v1.0.1 — 置顶应用不再霸占 Alt+Tab
修复
- 置顶应用不再霸占 Alt+Tab 列表:Windows 的 Z 序永远把置顶(WS_EX_TOPMOST)窗口排在最前——例如 PowerToys「窗口裁剪器」(Crop And Lock)裁剪出的窗口会一直钉在最顶层,此前它们因此总是成为 Alt+Tab 的第一个切换目标。现在切换顺序为:前台应用第一,其余非置顶应用按最近使用(Z 序)排列,置顶应用整体垫底(仍会出现在列表里,可通过点击卡片或继续按 Tab 到达)。
使用
Alt+Tab在应用之间切换(每个应用一个条目,macOS Cmd+Tab 风格);应用内窗口切换(如 PowerToys Window Hopper)继续使用各自的快捷键,二者完全分离。- 下载
AltTabSwitcher.exe双击运行即可(免安装),托盘图标可设开机自启。适用于 Windows 10/11 64 位。
SHA256: 97f35063d1a8643acdf43e90df6f48a6c3c6d4d5fc7537d480cb073e15a85137
AltTabSwitcher v1.0.0
特性
- 应用级 Alt+Tab:按进程分组、按最近使用(Z 序)排序,前台应用的兄弟窗口绝不出现,
Alt+Tab永远直接落到另一个应用;应用内窗口切换交给Alt+(反引号,如 PowerToys Window Hopper),与 macOS 的 Cmd+Tab / Cmd+` 双轨完全一致。 - Window Hopper 风格 UI:浮层移植自 PowerToys 的 AltWindowCycle 模块——WinUI 风格圆角卡片、每卡片图标+标题、系统强调色双环选中框、跟随系统深浅主题、分页与页码、无背景变暗。
- DWM 实时缩略图:与任务栏预览同机制的实时画面,按卡片比例居中裁剪,不拉伸变形。
- 完整鼠标支持:点击卡片直接切换、点击面板外任意位置取消、滚轮循环;
Esc同样取消。 - 虚拟桌面感知:只列出当前桌面的应用,切换永不把窗口拽到其他桌面。
- 零侵入:纯浮层 UI,不修改任何其他窗口的样式、可见性、归属或任务栏属性,崩溃无残留。
- 按显示器居中、DPI 感知、最多 6 列自动分页;单文件绿色 exe,Windows 自带编译器即可构建(Win10/11 64 位)。
使用
下载 AltTabSwitcher.exe 双击运行,托盘图标右键可设开机自启。
SHA256: 3953f174a48e796c9a088762a0f644677ce64ea24c091ef9ea0421c83e9841af