退休|IContextMenu第六部分:显示菜单帮助信息


退休|IContextMenu第六部分:显示菜单帮助信息
文章图片
退休|IContextMenu第六部分:显示菜单帮助信息
文章图片
退休|IContextMenu第六部分:显示菜单帮助信息
文章图片
退休|IContextMenu第六部分:显示菜单帮助信息
文章图片
关于上下文菜单 , 还有一个值得关注的地方是在状态栏上显示对应的帮助信息 。 到目前为止 , 我们的例子程序还没有涉及到状态栏 , 但是没关系 , 为了演示今天的主题 , 我们将菜单帮助信息显示在窗口的标题栏 , 也是一样的效果 。 正文即将开始 , 请做好扶稳 。
关于菜单帮助信息 , 一个关键的接口方法是
IContextMenu::GetCommandString , 它主要用来和上下文菜单处理器进行通信 。 为了方便演示 , 我再一次地将本应该声明为成员的变量声明为了一个全局变量 , 但实际工程开发中 , 请尽量避免全局变量的使用 。
【退休|IContextMenu第六部分:显示菜单帮助信息】
在我们调用TrackPopupMenuEx的前后 , 我们将对这个变量进行更新 , 如下图所示:
做好了如上的准备工作之后 , 我们就可以开始编写代码 , 实现在用户浏览上下文菜单项时显示对应的帮助信息了 , 我们先看看下面的代码:
这个函数首先检查被选中的菜单是否位于我们定义的范围 , 如果是 , 则我们通过调用GetCommandString方法来获取对应的帮助信息 , 并显示在窗口的标题栏上 。
最后 , 我们将这个函数集成到我们的窗口过程中 。 我们希望即使上下文菜单处理器会对菜单做后续的操作 , 我们也能更新菜单项的选中状态并显示在窗口的标题栏上 , 所以 , 这里我们在将消息分发到菜单处理器之前就调用了我们定义的OnMenuSelect函数 , 如下图所示:
先等会细心的读者可能发现了 , 在上面的代码中 , 我们有一条注释说以下代码可能存在Bug , 具体是什么神仙Bug呢?
请稍安勿躁 , 其实技术上来说 , 也没有什么Bug , 只是 , 当你尝试运行这段代码的时候 , 你会觉察到程序的行为有些怪异 。
这是因为 , 有一些上下文菜单处理器没有很好地实现 , Bug也源自于此 。
有一些处理器没有支持Unicode , 有一些则没有支持ANSI 。 更加有意思的是 , 他们没有实现对应的代码 , 同时 , 没有按照惯例返回E_NOTIMPL错误代码 , 而是直接返回了S_OK 。 还有另外一些处理器存在潜在的缓冲区溢出问题 , 他们会在超出内存边界的位置写入数据 。
很好 , 欢迎大家再次来到应用程序兼容性的世界 。
下面我们来写一个帮助函数 , 试着解决上面所提到的各种问题 。
在外壳代码实现中 , 类似于上面的代码随处可见 。
接下来 , 我们将这个帮助函数集成到OnMenuSelect中 , 如下图所示:
新的版本可以正确地显示被支持的菜单项帮助信息 , 也能容忍一些未能正确实现的处理器错误 , 甚至是一些比较严重的安全性问题 , 例如缓冲区溢出问题 。
好了 , 今天的支线任务就先到这里 。 在下一篇文章中 , 我们将回到主线 , 即默认操作的调用 。
总结其实获取帮助信息的实现并不复杂 , 只是你需要面对一个不那么完美的真实世界 。
为了保持兼容性 , 还得在设计上多考虑各种意外情况 , 在代码上也多下些功夫 。
最后Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一 , 里面有很多关于Windows的小知识 , 对于广大Windows平台开发者来说 , 确实十分有帮助 。
本文来自:《How to host an IContextMenu part 6 – Displaying menu help》