IContextMenu::QueryContextMenu 返回不相关的菜单

IContextMenu::QueryContextMenu return not relevant menu

提问人:Asaq 提问时间:1/13/2016 最后编辑:Jishan ShaikhAsaq 更新时间:2/2/2023 访问量:1015

问:

网络连接快捷方式(以太网、Wi-Fi 等)根据连接状态(已连接/已断开连接)具有不同的上下文菜单。 我使用以下代码(Delphi)来检索和显示此菜单。

var pidl, child: PItemIdList;
    pFolder: IShellFolder;
    pMenu: IContextMenu;
    menu: HMENU;
begin
  SHParseDisplayName(PChar('%USERPROFILE%\Desktop\eth0.lnk'), nil, pidl, 0, PDWORD(nil)^);
  SHBindToParent(pidl, IID_IShellFolder, Pointer(pFolder), child);
  CoTaskMemFree(pidl);
  pFolder.GetUIObjectOf(0, 1, child, IID_IContextMenu, nil, pMenu);
  menu := CreatePopupMenu;
  pMenu.QueryContextMenu(menu, 0, 0, $7fff, CMF_NORMAL);
  TrackPopupMenuEx(menu, TPM_LEFTBUTTON, 0, 0, Handle, nil);
  DestroyMenu(menu);
end;

但是更改连接状态后,我不断收到旧菜单。重新启动应用程序后,我有时会获得正确的菜单,但是,大多数时候我没有。

为什么会发生这种情况以及如何解决?

操作系统: both 32- and 64-bit Windows 7/8/10

C++ 代码:

PIDLIST_ABSOLUTE pidl;
if SUCCEEDED(SHParseDisplayName(L"%USERPROFILE%\\Desktop\\eth0.lnk", NULL, &pidl, 0, NULL))
{
  PCUITEMID_CHILD child;
  CComQIPtr<IShellFolder> pFolder;
  if SUCCEEDED(SHBindToParent(pidl, IID_IShellFolder, (void**)&pFolder, &child))
  {
    CComQIPtr<IContextMenu> pMenu;
    if SUCCEEDED(pFolder->GetUIObjectOf(0, 1, &child, IID_IContextMenu, NULL, (void**)&pMenu))
    {
      HMENU menu = CreatePopupMenu();
      if SUCCEEDED(pMenu->QueryContextMenu(menu, 0, 0, 0x7fff, CMF_NORMAL))
        TrackPopupMenuEx(menu, TPM_LEFTBUTTON, 0, 0, hWnd, NULL);
      DestroyMenu(menu);
    }
  }
  CoTaskMemFree(pidl);
}

加:也许是 Windows 错误。来自互联网和文件管理器(如资源管理器(XYPlorer、Explorer++ 等)的任何示例都存在相同的问题。现在我在 Windows 10 资源管理器上看到了同样的问题。如果您通过拖放从桌面上的“控制面板\所有控制面板项\网络和共享中心\更改适配器设置\adapter_name”创建网络连接的快捷方式,则会看到相同的问题。

C++ Delphi WinAPI ContextMenu Windows-Shell

评论

0赞 Jonathan Potter 1/19/2016
菜单是否会立即在资源管理器中更新?也许只是需要一点时间。
0赞 Asaq 1/19/2016
是的,菜单会立即在资源管理器中更新。Shell扩展没有这个问题,例如经典Shell - 开始菜单,但是如果它在单独的进程(不是Explorer.exe)中运行,它将有同样的问题。
0赞 CodeJunkie 4/13/2022
它可能会在您右键单击快捷方式后更新,而不是在以编程方式获取它时更新。尝试以不同的方式获取统计数据或以某种方式刷新状态。
0赞 Iziminza 4/24/2022
不,正如 OP 后来添加的那样,即使在 Windows 资源管理器窗口中,快捷方式上下文菜单也不会更新。只有“控制面板”中的原始版本才具有正确的上下文菜单。

答:

0赞 Lemonina 2/2/2023 #1

我认为问题与缓存的网络连接快捷方式的上下文菜单信息有关,当您更改连接状态时,Windows 可能不会自动刷新缓存的信息。

您可能需要通过调用函数手动刷新缓存,它将通知系统应用程序已执行的事件并触发缓存刷新。
下面是 Delphi 中的一个示例:
SHChangeNotify

begin
// ... your code here ...

SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;

在 C++ 中:

SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);

若要确保上下文菜单是最新的,请在显示之前尝试调用。SHChangeNotify