阿里巴巴|IContextMenu第十一部分:组合扩展的实现

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片

阿里巴巴|IContextMenu第十一部分:组合扩展的实现

文章图片


现在 , 我们已经有两个菜单处理器了 , 一个是来自外壳的上下文菜单 , 另一个是我们自定义的菜单(包含两个自定义菜单项) , 下面我们看看如何将它们组合在一起 。 具体来说 , 我们会使用到一个组合上下文处理器来实现 。
组合上下文菜单的核心思想是将多个上下文菜单组合到一个处理器中 , 并使用菜单标识符的偏移来对菜单项进行路由和定位 。
请看下面的代码 。


在上面的代码中 , 我们使用到了一个结构体CONTEXTMENUINFO , 它包含了菜单中的一些信息 。 我们不仅需要上下文菜单指针 , 而且也需要被
IContextMenu::QueryContextMenu使用到的菜单项的数量 。
下面的代码演示了我们如何实现这个类 。

因为对于一个C++对象来说 , 它的构造函数不会失败 , 因此在构造过程中如何处理失败有多种设计惯例 。 我在这里使用的一个设计是 , 将大部分工作放在Initialize方法中 , 如果初始化失败 , 该方法可以返回适当的错误代码 。 (请注意 , 这里我假设new操作符不会抛出异常)
我们的初始化函数分配了一堆CONTEXTMENUINFO结构并复制IContextMenu指针以妥善保管 。 (注意 m_ccmi 成员直到我们知道内存分配成功后才会设置 。 )
下面是类的析构函数实现:

接下来是Create方法的实现:

因为我们的接口继承自IUnknown接口 , 所以还需要实现IUnknown接口的三个方法 , 如下图所示:

接下来 , 是一个我们比较感兴趣的方法实现:
IContextMenu::QueryContextMenu 。

我们依次要求每个包含的上下文菜单将其命令添加到上下文菜单中 。 你可以在此处看到
IContextMenu::QueryContextMenu 方法返回值的原因之一 。通过告诉容器使用了多少个菜单标识符 , 容器知道还剩下多少给其他人使用 。然后容器返回所有上下文菜单使用的菜单标识符总数 。

IContextMenu::QueryContextMenu 方法返回值的解释请看下面的帮助函数:

此方法采用菜单偏移量并计算出它属于哪个包含的上下文菜单 , 使用来自
IContextMenu::QueryContextMenu 的返回值来决定如何划分标识符空间 。pidCmd 参数是输入/输出 。进入函数时 , 它是复合上下文菜单的菜单偏移量; 退出函数时 , 它是包含的上下文菜单的菜单偏移量 , 通过 ppcmi 参数返回 。
【阿里巴巴|IContextMenu第十一部分:组合扩展的实现】
IContextMenu::InvokeCommand 可能是最复杂的 , 因为它需要支持四种不同的命令调度方式 , 请看下图: