Windows 11重新设计了右键菜单,如何适配,是一个问题。

介绍

首先看Windows Blogs的这篇博文Extending the Context Menu and Share Dialog in Windows 11

  • 新款右键菜单也可以用于不封包的Win32应用。
  • 新款的改进主要针对的问题
    • 利用横向空间,改善纵向列表的拖沓
    • 有些挨劈劈添加完右键菜单之后就置之不理
      • 挨劈们通过IExplorerCommand以及挨劈劈标识来扩展菜单
    • 许多命令在Explorer的进程内运行,拖慢了Explorer
  • 右键菜单最佳实践
    • 关联的文件类型的挨劈劈会自动添加到Open with菜单组
      • 针对所有文件类型的,可以注册*
    • 注册Edit with (app)
      • 如HTML这类文件,查看和编辑需要分开,于是就要另注册Edit with(app)菜单项
    • 注册Share with (app)
      • 暂不关注

此外,上文中还提供了改进款的分享对话框,例子如https://github.com/microsoft/AppModelSamples/tree/master/Samples/SparsePackages

文档:IExplorerCommand interface (shobjidl_core.h)

IExplorerCommand直接继承自IUnknown,有如下成员:

  • EnumSubCommands,返回IEnumExplorerCommand,可用于遍历子命令,也就是在下拉菜单中显示的命令
  • GetCanonicalNa,获取菜单命令的GUID命名
  • GetFlags,设置菜单命令的风格样式
  • GetIcon,获取图标
  • GetState,获取状态
  • GetTitle,获取标题
  • GetToolTip,获取使用提示
  • Invoke,调用命令
    • IShellItemArray给出选中的条目
    • IBindCtx

文档:How to Create Cascading Menus with the IExplorerCommand Interface

提到可以通过IExplorerCommand::EnumSubCommands来提供子菜单。

SO帖子:How to write a Shell extension in C++ for new Windows 11 context menus?

其他:

例子1

https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appshellintegration/ExplorerCommandVerb

Old Windows 7 example。

例子2

https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/CloudMirror

使用CoRegisterClassObject,在进程内起一个线程提供COM服务。

参考

例子3

https://github.com/ikas-mc/ContextMenuForWindows11

未仔细研究

例子4

https://github.com/M2Team/NanaZip

使用cppwinrt实现了一个子菜单,代码在https://github.com/M2Team/NanaZip/blob/main/NanaZipShellExtension/NanaZipShellExtension.cpp

知识:启动封包的程序

可以使用Windows.System.Launcher,也可以使用

  • Windows.ApplicationModel.Package下AppList的LaunchAsync
  • 或者Win32的IActivateApplication

使用ActivateApplication的一个例子:

        winrt::com_ptr<IApplicationActivationManager> appActivationMgr = nullptr;

        RETURN_IF_FAILED(
            CoCreateInstance(CLSID_ApplicationActivationManager, nullptr,
                             CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(appActivationMgr.put())));

        DWORD processId;

        appActivationMgr->ActivateApplication(
            app.AppUserModelId().c_str(),
            nullptr,
            AO_NONE,
            &processId);

appActivationMgr->ActivateForFile在WindowsAppSdk中不可用。

其他

(到底了)