【问题标题】:COM IContextMenu::InvokeCommand - matching LPCMINVOKECOMMANDINFO::lpVerb to itemCOM IContextMenu::InvokeCommand - 匹配 LPCMINVOKECOMMANDINFO::lpVerb 到项目
【发布时间】:2015-10-24 14:45:13
【问题描述】:

我使用COM 为 Windows 创建了一个 shell 扩展,但是我似乎无法正确匹配我在 IContextMenu::QueryContextMenu 的重载中添加的项目的 ID 与我在 IContextMenu::InvokeCommand 的重载中收到的 ID。在我的代码中,我使用了InsertMenuInsertMenuItem(据我了解,它们的作用相同,但后者具有更多功能?)。但是我不确定传递给InsertMenu/InsertMenuItem 的哪些参数对应于我必须在LPCMINVOKECOMMANDINFO::lpVerb 中寻找的参数。我需要一些方法来轻松知道当我将项目xyz 添加到上下文菜单时,我可以准确地知道xyz 中的哪一个已被点击.

编辑:似乎动词等于当前菜单/子菜单中项目从上到下的数字。但是,我有两个子菜单,每个子菜单都有x 的项目数量,因此它们具有相同的 ID 1、2、3。如何设置自定义 ID 或其他内容?

【问题讨论】:

  • 不要要说明书,已经写好了。显示您的代码。
  • 写在哪里?
  • @HansPassant 我似乎找不到能很好解释这一点的手册,只有一个在线教程,它只添加了一个动词,你总是知道它就是那个
  • 我怀疑你得到的lpVerb 可能是MAKEINTRESOURCE(yourCommandId)。请与IS_INTRESOURCE 联系。或者,它可以是您通过实现IContextMenu::GetCommandString(GCS_VERB{A|W}) 与命令关联的任何动词
  • 这在此处记录:msdn.microsoft.com/en-us/library/windows/desktop/hh127443.aspx。在本文档中,一个自定义命令“IDM_DISPLAY”作为示例完全实现。

标签: c++ com contextmenu shell-extensions


【解决方案1】:

首先,您应该定义一个枚举来保存菜单项的命令 ID,例如

enum {
    CMDID_FIRST = 0,

    CMDID_DOSOMETHING = CMDID_FIRST,
    CMDID_DOSOMETHINGELSE,

    CMDID_LAST,
};

这些ID值需要从0开始。

在您的IContextMenu::QueryContextMenu 实现中:

  • 添加菜单项时,您需要通过在MENUITEMINFO.fMask 字段中设置MIIM_ID 标志并设置MENUITEMINFO.wID 值来为每个菜单项指定一个ID。

  • 为您的每个菜单项提供一个从上面定义的命令 ID 派生的 ID,加上 idCmdFirst 的值,该值被传递到QueryContextMenu。例如。 “做某事”菜单项会将MENUITEMINFO.wID 设置为idCmdFirst + CMDID_DOSOMETHING,而“做其他事情”会将MENUITEMINFO.wID 设置为idCmdFirst + CMDID_DOSOMETHINGELSE

  • QueryContextMenu 的返回值必须是 MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, x),其中 x 是您添加的编号最高的项目的 ID 加 1(或者,如果所有项目都按顺序编号,项目总数)。基本上,您是在告诉主机当前正在使用哪些菜单项 ID 值,以便没有其他上下文菜单扩展添加与您的项目冲突的项目。在上面的示例中,您将返回 MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, CMDID_LAST)

IContextMenu::InvokeCommand:

  • 使用IS_INTRESOURCE 宏测试lpVerb(或lpVerbW)是否为整数值。
  • 如果是这样,可以在低位字中找到命令 ID。例如,如果用户选择“做其他事情”,您会发现 LOWORD(lpVerb) == CMDID_DOSOMETHINGELSE

【讨论】:

  • 你知道为什么QueryContextMenuInvokeCommand 之间存在某种不对称,因为你在第一种方法中添加了idCmdFirst 偏移量,但你没有在第二种方法中减去它?
  • @loop123123 我猜测主机在调用您的命令时会减去该值以方便您。否则,您需要将idCmdFirst 存储在某处(因为它没有作为调用的一部分传递)。添加时您需要进行数学计算,因为您是实际创建菜单项的人,并且 ID 是菜单项的组成部分。
  • 酷,谢谢。我建议添加的一件事是,如果您不处理InvokeCommand 中的命令,则需要返回E_FAIL。否则,您将完全搞乱其他上下文菜单命令。我刚刚学会了这一点。
  • @loop123123 是的,这在文档中。 如果上下文菜单处理程序无法识别由规范动词名称或命令 ID 指定的动词,则它必须返回失败 (E_FAIL),以便可以将动词传递给其他上下文菜单处理程序实施它。
  • 您愿意就我的方法提供任何反馈吗? stackoverflow.com/a/62374937/13366655
猜你喜欢
  • 2011-12-04
  • 1970-01-01
  • 2020-12-13
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多