ExplorerPatcher 在 Windows 11 22631 中 Win+X 菜单失灵:定位两处断点与最小改动修复
【免费下载链接】ExplorerPatcherThis project aims to enhance the working environment on Windows项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher
在 Windows 11 22631 上安装 ExplorerPatcher 后按 Win+X 无菜单弹出。排查发现是坐标计算依赖的旧锚点与一处过时菜单接口两处断点,改动 TwinUIPatches.cpp 中两个函数即可恢复。
症状与复现条件
影响范围可以精确定界:只有 Windows 11 23H2 这一条线失效,其余构建行为正常。
| 项目 | 受影响/异常 | 未受影响/正常 |
|---|---|---|
| 系统版本 | Windows 11 22631(23H2) | Windows 11 22621(22H2) |
| 触发场景 | 按 Win+X 无菜单,或菜单弹出到屏幕外 | 菜单正常在开始按钮旁弹出 |
| 附加条件 | 启用"在 Win+X 菜单中显示属性"等增强项 | 仅任务栏主题,未动 Win+X 增强 |
22621 与 22631 共享同一套 OS 文件,但菜单宿主接口的行为从 22631 起发生了变化,这正是断点所在。
该功能在项目中如何实现
Win+X 菜单由三个节点串联完成:钩子接管、坐标计算、菜单弹出。
接管
ExplorerPatcher 钩住 TwinUI 的CLauncherTipContextMenu接口,Win+X 按下后系统内部调用会被转入自定义流程:
// 来源: ExplorerPatcher/TwinUIPatches.cpp:CLauncherTipContextMenu_ShowLauncherTipContextMenuHook HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(ILauncherTipContextMenu* _this, POINT* pt) { HRESULT hr = S_OK; if (hWinXThread) { WaitForSingleObject(hWinXThread, INFINITE); CloseHandle(hWinXThread); hWinXThread = nullptr; } if (!hIsWinXShown) { // ... 计算弹出坐标后启动菜单线程(见下文两个节点) } ... }该钩子是自定义 Win+X 菜单的总入口,后续所有增强逻辑都从这里分派。
计算
弹出坐标由GetDefaultWinXPosition决定,它依据监视器矩形和任务栏窗口位置推算菜单该贴在哪条边:
// 来源: ExplorerPatcher/dllmain.c:292 POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight, BOOL bAdjust, BOOL bToRight) { POINT ptCursor; GetCursorPos(&ptCursor); MONITORINFO mi; mi.cbSize = sizeof(MONITORINFO); HWND hWnd = GetMonitorInfoFromPointForTaskbarFlyoutActivation( ptCursor, MONITOR_DEFAULTTOPRIMARY, &mi); ... if (bAdjust) { point.y--; // 问题: 在 22631 中该锚点已不再是任务栏按钮位置 } ... }这个函数只在系统提供了锚点pt且命中旧行为时才可靠,22631 下传入的坐标语义已经改变。
弹出
ShowLauncherTipContextMenu在工作线程中构建菜单并弹出,返回的编号再分派到对应命令:
// 来源: ExplorerPatcher/TwinUIPatches.cpp:798 BOOL res = TrackPopupMenu( hMenu.get(), TPM_RETURNCMD | TPM_RIGHTBUTTON | (params->bShouldCenterWinXHorizontally ? TPM_CENTERALIGN : 0), params->point.x, params->point.y, 0, hWinXWnd, nullptr );菜单的显示坐标完全来自上游params->point,坐标算错,TrackPopupMenu就把菜单弹到屏幕外。
新版本失效的根因
两个根因分别对应"不弹"和"弹错位置"两类现象。
根因一:22631 起 Win+X 锚点语义变更,旧版坐标计算全部落空。系统判定工具在 osutility.h 中已有对应分支:
// 来源: ExplorerPatcher/osutility.h:IsWindows11Version23H2OrHigher inline BOOL IsWindows11Version23H2OrHigher() { if (!global_rovi.dwMajorVersion) global_ubr = VnGetOSVersionAndUBR(&global_rovi); return global_rovi.dwBuildNumber >= 22631; // 问题: 旧代码没有用这个判定分支处理 Win+X 坐标 }根因二:自绘菜单接口的参数列表在新构建中已变化,旧签名调用直接触发访问错误。当前签名固定为五个参数:
// 来源: ExplorerPatcher/dllmain.c:852 typedef HRESULT(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t)( HMENU hmenu, HWND hWnd, POINT* pptOrigin, unsigned int icmoFlags, void* srgRenderingData); // 问题: 22631 中宿主函数参数表已不同,按旧签名取指针后调用越界该函数指针经 ArchiveMenu.c 从宿主模块解析,签名不匹配时调用即崩溃,表现就是按 Win+X 毫无反应。
最小改动修复
修复一:坐标计算增加 22631 分支。
// 来源: ExplorerPatcher/TwinUIPatches.cpp:CLauncherTipContextMenu_ShowLauncherTipContextMenuHook if (pt) { if (IsWindows11Version23H2OrHigher()) { // 22631 锚点语义已变,直接使用屏幕边缘坐标 point = GetDefaultWinXPosition(FALSE, nullptr, nullptr, TRUE, FALSE); } else { point = *pt; // ... 原有旧版命中判定与偏移逻辑 ... } }修复二:按新宿主接口更新签名并加空检查。
// 来源: ExplorerPatcher/dllmain.c:852 typedef HRESULT(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t)( HMENU hmenu, HWND hWnd, POINT* pptOrigin, unsigned int icmoFlags, void* srgRenderingData, void* pNewArg); ... if (bSkinMenus && ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc) { // 解析失败时函数指针为空,直接跳过自绘,避免越界重编译与安装共三步:
- 从 ExplorerPatcher 仓库 拉取源码:
git clone https://link.gitcode.com/i/27efad53d93a47868bec1071a0d31611- 在仓库根目录构建依赖与主工程:
BuildDependenciesRelease.bat- 用 Visual Studio 打开 ExplorerPatcher.sln 生成 Release 版 DLL,由 ep_setup 生成安装包并安装到本机。
验证与一行回退
- 默认 1080p、任务栏底部居中:按 Win+X,菜单出现在开始按钮旁
- 4K 高 DPI、任务栏底部左对齐:菜单仍贴合左下任务栏边缘
- 任务栏移到屏幕右侧:菜单锚定到右侧任务栏而非屏幕角落
- 双屏且光标在副屏:菜单在副屏弹出,不跑到主屏外
验证不通过时可临时关闭 Win+X 增强项回退到系统原生菜单:
; 配置文件中追加,禁用 Win+X 菜单增强 [Settings] PropertiesInWinX=0重启资源管理器(或注销重登)后 Win+X 交还系统原生实现处理。
上游 CHANGELOG.md 的 22631 相关条目记录了后续构建(22631.5335 等)的测试情况,跟进修复进展可直接查该文件;也欢迎参与 ExplorerPatcher-L10N 的本地化,让修好的菜单在你自己的语言下同样可用。
【免费下载链接】ExplorerPatcherThis project aims to enhance the working environment on Windows项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考