Repository navigation
fix(context-menu): re-snapshot lazily populated system submenus (items missing in "Send to" / "New") - #846
Open
v4806 wants to merge 1 commit into
Open
fix(context-menu): re-snapshot lazily populated system submenus (items missing in "Send to" / "New")#846v4806 wants to merge 1 commit into
v4806 wants to merge 1 commit into
Conversation
现象
Win10 上 Shell 菜单里的「发送到」子菜单只显示 3~5 项,且每次内容都不一样;
原生菜单稳定有 9 项。丢的是「压缩(zipped)文件夹」「桌面快捷方式」「邮件收件人」
「文档」以及驱动器项 —— 即所有非 .lnk 的 shell 扩展项。
根因
Shell 在 Initialize()(IContextMenu::QueryContextMenu 阶段)就把原始菜单抓成快照
(build_system_menuitems),但 shell32 是惰性填充的:那一刻「发送到」子菜单里
只有几个 .lnk 项,其余 shell 扩展项和驱动器项还没加进去,快照因此残缺。
而该子菜单真正弹出(WM_INITMENUPOPUP 指向它)时,原始句柄已经补齐,
但 OnInitMenuPopup 只重放旧快照,于是永远丢项。
修法
- menuitem_t 记录抓快照时对应的原始子菜单句柄 source_handle;
menu_t 记录它所对应的 menuitem_t(std_owner)。
- OnInitMenuPopup 中,若 GetMenuItemCount(source_handle) > 快照项数,
就清空并用 build_system_menuitems() 对原始句柄重抓 —— 仍然走 Shell 自己的
menuitem_t 路径。不直接拷贝原始 HMENU 里的项:那些是 explorer 的 owner-draw 项
(dwItemData 指向 explorer 的数据),直接插入会画不出来。
- 主菜单弹出时对整树刷新一次,作为兜底。
验证
Win10 22H2 + Shell 1.9.19,桌面 .lnk 右键 → 更多选项 → 发送到:
修复前 3 项,修复后稳定 9 项(连续 4 轮,含 explorer 重启)。
运行时日志: [FIX] refetch '发送到(&N)' snapshot=3 now=9
未触发重抓时行为与改动前完全一致(纯新增代码 + 一处条件调用)。
Author
|
Also reported as #749, #464, #614, #815 — all four look like the same root cause: shell32 fills the "Send To" submenu lazily, but Shell takes its snapshot of the original menu much earlier (during 同一根因的其它报告:#749、#464、#614、#815 —— shell32 是惰性填充「发送到」子菜单的,而 Shell 抓快照的时机远早于此( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
System submenus that Shell takes from the original menu can lose items and vary between openings,
while the native menu is always complete. Most visible in Send to: only 3-5 of the 9 items appear,
and a different subset each time. The same symptom has been reported for the New submenu and for
certain file types.
Affects both Windows 10 and Windows 11 - see #749 (also reported there on Win 11 25H2) and #815
(also reported there on Win 11 23H2), plus #464 and #614.
Root cause
build_system_menuitems()snapshots the original menu duringInitialize(), i.e. in theIContextMenu::QueryContextMenuphase. But shell32 fills these submenus lazily: at that momentonly a few items exist, so the snapshot is incomplete. When the submenu actually pops up, explorer's
original handle already contains the full set, yet
OnInitMenuPopup()only replays the stalesnapshot.
Fix
menuitem_tgainsHMENU source_handle- the original submenu handle, recorded while snapshotting.menu_tgainsmenuitem_t *std_owner- points back to its snapshot item.OnInitMenuPopup(), ifGetMenuItemCount(source_handle)exceeds the snapshot count, the snapshotis cleared and rebuilt from the original handle; the main menu refreshes the whole tree once as a
safety net.
Rebuilding through Shell's own
build_system_menuitems()is required: copying the items out ofexplorer's HMENU with
InsertMenuItemWcannot work, because they are owner-draw items whosedwItemDatapoints at explorer-internal data.The change is purely additive plus one conditional call - when
source_count <= snapshot_countthebehaviour is exactly as before.
Verification
Windows 10 22H2 + Shell 1.9.19, desktop shortcut -> More options -> Send to:
I could not test Windows 11 myself, but the mechanism is version-independent (the snapshot is taken
before shell32 populates the submenu) and the same symptom is reported there in #749/#815.