技法和原理:如何找到你需要的菜单项?
你一定碰到过查找某个菜单项的场景,通常我们会使用类似于 GetMenuItemInfo 这样的菜单函数,
在这类函数中,有一个参数允许你指定要查找的菜单项目的信息:MF_BYPOSITION 或者 MF_BYCOMMAND。
至此,是不是很眼熟了。今天就来给大伙儿讲讲这个。
从字面意思来理解,MF_BYPOSITION 是根据菜单的位置来进行查找,而 MF_BYCOMMAND 是根据菜单的命令 ID 来进行查找。
根据菜单的位置进行查找是很容易理解的,我们指定一个从 0 开始的数字作为菜单的位置进行菜单项的查找。换句话说,索引 0 表示第一个菜单项,依次类推。
根据菜单命令进行查找,有些小复杂,请坐稳扶好:菜单管理器将会根据你指定的菜单命令对整个菜单进行递归式查找,包含子菜单。很有可能发生的情况是,有可能在整个菜单树中会找到多个拥有同一个命令的菜单项,这个时候,函数将会从中任意选择一个出来返回给你。
例如,在层次结构中查找意味着只需传递根菜单(通常可以轻松访问)和菜单命令即可删除或禁用菜单项。
如果不搜索子菜单,那么同步菜单状态将是一件非常麻烦的事情。
但是,如果您的菜单有多个具有相同命令的项目怎么办?
好吧,简短的回答是,”那就不要用MF_BYCOMMAND了。您仍然可以使用 MF_BYPOSITION 来访问您的菜单项。”
但我对你的灵魂之问是:
为什么首先要有多个具有相同命令的菜单项呢?
当用户选择菜单时,一条 WM_COMMAND 消息将发送到窗口,并将菜单命令作为其参数之一,而其他参数均不提供菜单句柄。如果您有多个具有相同命令的菜单项,您将无法分辨用户选择了其中的哪一个,这可不是你想要的。
对于这个问题,已经有过很多讨论了,但是我想说的是,这并非 Windows 的 Bug 。
如果菜单包含多个具有相同命令的菜单项,那么 MF_BYCOMMAND 是模棱两可的,并且所承诺的只是将找到具有该命令的某些项目。它可能不是您想要的,但由于您为多个项目提供了相同的命令,因此菜单管理器已尽最大努力。
这类似于其他搜索函数,如 FindWindow 和 GetDlgItem,它们对它们找到的第一个项目进行操作。如果多个项目符合您指定的条件,则仅返回其中一个项目。
另外还有一个具体问题:查询菜单的时候,恰好没有缓存,至少现在还没有。但谁知道呢,如果我们发现许多应用程序快速连续地查询同一项目,将来可能会有一个缓存。但是这个人没有意识到的是,他们使用的未命名的自定义 GUI 库在收到 WM_INITMENUPOPUP 消息之前不会创建子菜单。在打开子菜单之前找不到该项目的原因是,在打开子菜单之前,子菜单不存在。当然,你找不到不存在的东西。
总结
优先使用按位置进行菜单项目查找,并时刻牢记:按命令查找可能会找到多个,且可能返回那个你所不需要的。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《How do the menu functions find items?》
最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。
相关推荐
- 新玩意儿更新:C++编码规则及最佳实践
- Posted on 08月24日
- vcpkg更新: C/C++代码管理利器
- Posted on 08月27日
- 为什么进程最多只能创建 10000 个窗口?
- Posted on 03月28日
- 实战经验:在控制台应用程序中使用自定义图标
- Posted on 05月06日
评论已关闭。