《Windows API每日一练》9.2.1 菜单

和菜单有关的概念

窗口的菜单栏紧挨着标题栏下面显示。这个菜单栏有时叫作程序的“主菜单”或“顶级菜单“(top-level menu)。顶级菜单中的菜单项通常会激活下拉菜单(drop-downmenu),也 叫“弹出菜单”(popup menu)或“子菜单”(submenu)。你可以定义多级嵌套的弹出菜单: 一个弹出菜单项可以激活另一个出菜单。有时弹出菜单项可以激活对话框来提供更多信息。(对话框在第十章讨论。)许多父窗口在标题栏的最左边显示程序的小图标。这个图标会激活系统菜单,该菜单实际上是另一种弹出菜单。

●弹出菜单的菜单项可以被“选中”(checked),亦即Windows在菜单文本左边显示一个 小的选中标记。选中标记的使用让用户可以选择不同的程序选项。这些选项可以是互相排斥的,当然不是必须要这样做。顶级菜单项不能被选中。

●顶级菜中或弹出菜单的菜单项可以被“启用”(enabled)、“禁用”(disabled)或“变灰”(grayed)。单词“活动”(Active)和“非活动” (Inactive)有时可以和“启用”和“禁用”同义使用。标记为启用或禁用的菜单项对用户来讲看起来一样,但变灰菜单项显示为灰色文本。

从用户的角度看,启用、禁用或变灰的菜单项都能被“选择”(加亮)。也就是说,用户可以在禁用的菜单项上单击鼠标,或者将反色显示(reverse-video)的光标条移动到一个禁 用的菜单项,或者使用菜单项的快捷键字母来触发禁用的菜单项。然而,从程序的角度,启用、 禁用或变灰的菜单项功能不同。Windows只向被启用的菜单项发送WM_COMMAND消息。对当前无效的菜单选项你可使用禁用或变灰的办法。如果你想让用户知道选项是无效的,最好将它变灰。

差别

主菜单(顶级菜单)

子菜单(弹出菜单)

被选中(checked)

不能

可以

启用/禁用  enabled/disabled

活动/非活动(Active/Inactive

可以

可以

变灰(grayed

可以

可以

WM_COMMAND消息

启用时,可发送。禁用或变灰里不能

句柄

有独立句柄

有独立句柄

菜单结构

在程序中创建或修改菜单时,将顶级菜单和每个弹出菜单想象成独立的菜单会有利于理解。顶级菜单有一个菜单句柄,在顶级菜单中的每个弹出菜单也都有自己的菜单句柄,系统菜单(也是一个弹出菜单)也有一个菜单句柄。

每个菜单项由三个特征定义。第一个特征是菜单显示什么。这可以是一个文本字符串或是一个位图。第二个特征是一个ID号或一个指向弹出菜单的句柄,Windows会在 WM_COMMAND消息中把ID号发送给你的程序,而弹出菜单则在用户选择该菜单项时由 Windows显示出来。第三个特征描述了菜单项的属性,包括该菜单项是否被禁用、变灰或选中。

定义菜单

要使用VS给程序的资源脚本加入菜单,应从Insert菜单中选择Resource,然后选择Menu。然后你就可以交互式定义菜单。菜单中的每一项都有一个相关联的Menu Item Properties对话框,用来指示菜单项的文本字符串。 如果Pop-up框被选中,则该菜单项会激活一个弹出菜单,这时它没有相关联的ID。如果 Pop-up框没被选中,那么该菜单项会生成一个带有特定ID的WM_COMMAND消息。这两种类型的菜单项会分别以POPUP和MENUITEM语句的形式在资源脚本中出现。

图9-10 创建菜单项

在为菜单中的一项输入文本时,可以输入一个符号&来指示Windows在显示菜单时给 紧接着&的下一个字符显示下划线。用Alt键选择一个菜单项时,Windows就寻找这样一个 带下划线的字符。如果不在文本中包含字符&,下划线不会出现,Windows将会用菜单项文本的第一个字母来进行Alt键搜索。

如果在Menu Items Properties对话框中选择了 Grayed选项,则表示该菜单项是非活动

的,它的文本会变灰,并且不会产生WM_COMMAND消息。如果选择Inactive选项,则表示该菜单项是非活动的,不会产生WM_COMMAND消息,但是它的文本会被正常显示。 Checked选项会在菜单项的旁边加一个复选标记。Separator选项会在弹出菜单上绘制一条 水平的分隔线。

对弹出菜单中的菜单项,可以在字符串中使用分栏制表符\t。即使弹出菜单第一栏的字 符串很长,\t后面的文本也会被放置在右边足够远的新一栏中。当我们学习键盘加速键时,我们会看到它是如何工作的。字符串中的\a会将它后面的文本进行右对齐。

指定的ID值是Windows在菜单消息中发给窗口过程的数字。ID值在一个菜单中应该 是唯一的。按照惯例,我们 使用以IDM(ID for a Menu)开头的标识符。                       

图9-11 设置菜单属性

                                                              

●菜单的单个特征:

特征

说明

①显示内容

1、表示文本字符串或位图。

2、带&指示紧接的字符显示下划线,配合Alt键搜索

3Spparator绘制水平分隔线

4\t制表符后面的文本在新一栏中

5\a后面的文本进行右对齐

ID

该项为MENUITEM(菜单项):则为菜单ID,会发送WM_COMMAND

POPUP(弹出菜单): 为菜单句柄

③属性

是否被禁用、变灰或选中等。非活动时,不会产生WM_COMMAND消息。

                                  

在程序中引用菜单

大多数Windows应用程序在资源脚本中只有一个菜单。可以给该菜单指定一个与程序 名一样的文本名字。程序员经常使用程序名作为菜单名,这样同一字符串可以作为窗口类名、程序图标名和菜单名。然后程序可以在窗口类定义中引用这个菜单:

wndclass.IpszMenuName = szAppName;

虽然在窗口类中指定菜单是引用菜单资源的最通常的方法,但它不是唯一的方法。 Windows应用程序可以用LoadMenu函数把菜单资源加载到内存,这和前面描述的Loadlcon 和LoadCursor函数非常类似。LoadMenu返回一个菜单的句柄。如果在资源脚本中为菜单设定了一个名字,那么该语句看起来会像这样:

hMenu = LoadMenu (hlnstance, TEXT ("MyMenu"));

如果使用数字,那么LoadMenu调用格式如下:

hMenu = LoadMenu (hlnstance, MAKEINTRESOURCE (ID_MENU))

之后便可以把这个菜单句柄指定为CreateWindow的第9个参数:

hvmd = CreateWindow (TEXT ("MyClass"), TEXT ("Window Caption"),

WS_OVERLAPPEDWINDOW,

                            CW_USEDEFAULT, CW_USEDEFAULT,                    

                            CW_USEDEFAULT, CW_USEDEFAULT,                    

                            NULL, hMenu, hlnstance, NULL);

这种情况下,CreateWindow中指定的菜单会覆盖窗口类中指定的任何菜单。如果 CreateWindow的第9个参数是NULL,那么你可以认为窗口类中的菜单是基于该窗口类的 所有窗口的默认菜单。因此,你可以对基于同一窗口类的几个不同窗口使用不同的菜单。

还可以在窗口类中指定一个NULL菜单名,并在CreateWindow调用中使用一个NULL 菜单句柄,然后在窗口创建之后再给它指派一个菜单:

SetMenu (hwnd, hMenu);

这种形式可以让你动态地改变窗口的菜单。我们会在本章后面的NOPOPUPS程序中看到 这样的一个例子。

当窗口被销毁时,附加到该窗口的任何菜单也将被销毁。而在程序结束前,任何没有附加到窗口的菜单应该通过DestroyMenu调用被显式地销毁。

其他菜单命令

除了之前已经介绍的菜单函数,还有更多和菜单相关的有用函数。

●当你改变一个顶级菜单项时,该改动直到Windows重绘菜单栏时才会被显示出来。你 可以调用下面的语句来强制重绘:

DrawMenuBar (hwnd);

【注意】DrawMenuBar的参数是一个指向窗口的句柄,而非菜单句柄。

●可以使用如下语句来获得弹出菜单的句柄:

hMenuPopup = GetSubMenu (hMenu, iPosition);

其中iPosition是弹出菜单在顶级菜单中的索引(从0开始),hMenu代表顶级菜单。然后便可以在其他函数(例如AppendMenu)中使用该弹出菜单句柄。

●使用如下语句,可以获得顶级菜单或弹出菜单中现有菜单项的数目:

iCount = GetMenuICemCount (hMenu);

●可以使用下面的语句来获得弹出菜单中某个菜单项的菜单ID:

 id = GetMenuItemID (hMenuPopup, iPosition);

其中iPosition是该菜单项在弹出菜单中的位置(从0开始)。

●在MENUDEMO中,展示了如何使用下面的语句在弹出菜单中“选中”和“取消选中” 某个菜单项:

CheckMenuItem (hMenu, id, iCheck);

在MENUDEMO中,hMenu是顶级菜单的句柄,id是菜单ID,iCheck的值是MF_CHECKED 或MF_UNCHECKED。如果hMenu是弹出菜单的句柄,那么id参数可以是位置索引而非菜单ID。如果使用索引更加方便,那么你可以在第三个参数中包含MF_BYPOSmON:

CheckMenuItem (hMenu, iPosition, MF_CHECKED | MF_BYP0SITI0N);

EnableMenuItem和CheckMenuItem函数类似,不同之处在于第三个参数是 MF_ENABLED、MF_DISABLED、或MF_GRAYED。如果你在顶级菜单项上使用 EnableMenuItem,而该菜单项还有弹出菜单,那么你必须在第三个参数中使用 MF_BYPOSITION标识符,因为该菜单项没有菜单ID。我们会在本章后面的POPPAD2程序中看到EnableMenuItem函数的示例。HiliteMenuItem函数和CheckMenuItem以及 EnableMenuItem类似,但它使用标志MF_HILITE和MF_UNHILITE。这种加亮使用的是 反色显示(Reverse Video),在你在菜单项之间移动时Windows使用的就是这种加亮形式。 通常情况下不需要使用HiliteMenuItem。

●获取菜单中使用的是什么字符串?你可以调用下面的语句:

iCharCount = GetMenuScring (hMenu, id, pString, iMaxCount, iFlag);

iFlag可以是MF_BYCOMMAND(此时id是一个菜单ID)或者MF_BYPOSITION(此时id是 一个位置索引)。该函数复制至多iMaxCount个字符到pString,并返回复制的字符数。

●或者你想知道一个菜单项的当前标志,可以调用:

iFlags = GeCMenuSCaCe (hMenu, id, iFlag);

同样,iFlag是MF_BYCOMMAND或MF_BYPOSmON之一。iFlag参数是所有当前标志 的组合值。你可以针对 MF_DISABLED、MF_GRAYED、MF_CHECKED、 MF_MENUBREAK、MF_MENUBARBREAK 和 MF_SEPARATOR 标识符进行检测,以确定当前的标志。

●当应用程序不再需要菜单时,通过下面的语句可以销毀它:

DestroyMenu (hMenu) ;

这个函数使该菜单句柄无效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/375127.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

26.6 Django模型层

1. 模型层 1.1 模型层的作用 模型层(Model Layer)是MVC或MTV架构中的一个核心组成部分, 它主要负责定义和管理应用程序中的数据结构及其行为. 具体职责包括: * 1. 封装数据: 模型层封装了应用程序所需的所有数据, 这些数据以结构化的形式存在, 如数据库表, 对象等. * 2. 数据…

java中Error与Exception的区别

java中Error与Exception的区别 1、错误(Error)1.1 示例 2、 异常(Exception)2.1 示例 3、 区别总结 💖The Begin💖点点关注,收藏不迷路💖 当我们谈论编程中的错误(Error&…

STM32杂交版(HAL库、音乐盒、闹钟、点阵屏、温湿度)

一、设计描述 本设计精心构建了一个以STM32MP157A高性能单片机为核心控制单元的综合性嵌入式系统。该系统巧妙融合了蜂鸣器、数码管显示器、点阵屏、温湿度传感器、LED指示灯以及按键等多种外设模块,形成了一个功能丰富、操作便捷的杂交版智能设备。通过串口…

如何解决 PostgreSQL 中由于索引不当导致的性能下降问题?

文章目录 如何解决 PostgreSQL 中由于索引不当导致的性能下降问题一、常见的索引不当情况(一)缺失关键索引(二)过多的冗余索引(三)不合适的索引类型 二、如何发现索引不当的问题(一)…

docker-2

27.构建python应用镜像-dockerfile实践项目 1.基于官方的镜像,构建python代码运行环境 dockerfile 2.运行镜像,开启一个读写的容器空间(定制操作,将代码丢进去,运行调试) 3.提交这个变化的容器层数据&#…

生产英特尔CPU处理器繁忙的一天

早晨:准备与检查 7:00 AM - 起床与准备 工厂员工们早早起床,快速洗漱并享用早餐。为了在一天的工作中保持高效,他们会进行一些晨间锻炼,保持头脑清醒和身体活力。 8:00 AM - 到达工厂 员工们到达英特尔的半导体制造工厂&#…

数据库使用SSL加密连接

简介 数据库开通SSL加密连接是确保数据传输过程中安全性的关键措施,它通过加密数据、验证服务器身份、保护敏感信息、维护数据完整性和可靠性,同时满足行业标准和法规要求,进而提升用户体验和信任度,为企业的数据安全和业务连续性…

javaweb中的请求与响应--基于postman工具的应用(附带postman的详细安装步骤)

一、前言 后端的第一天感觉难度就上来了,可能是基础太过薄弱了吧。目前看视频已经有点跟不上了,果然15天想要拿下还是太勉强了点。30天还差不多。不知道读者们有没有好好的去学这方面的知识,没有什么是学不会的,关键是坚持。 Po…

Ubuntu22.04安装NIVIDIA显卡驱动总结

1.首先在安装驱动时需要判断系统有无GPU以及GPU的型号 可以参考这篇文章: https://blog.51cto.com/u_13171517/8814753#:~:textubuntu%20%E7%B3%BB%E7%BB%9F%20%E6%80%8E%E4%B9%88%E5%88%A4%E6%96%AD%E7%B3%BB%E7%BB%9F%E6%9C%89%E6%B2%A1%E6%9C%89GPU%201%20%E6%…

STM32实战篇:闪灯 × 流水灯 × 蜂鸣器

IO引脚初始化 即开展某项活动之前所做的准备工作,对于一个IO引脚来说,在使用它之前必须要做一些参数配置(例如:选择工作模式、速率)的工作(即IO引脚的初始化)。 IO引脚初始化流程 1、使能IO引…

乐观锁原理

乐观锁是一种并发控制的方法,主要用于多线程环境下,用于保证数据的一致性。其核心思想是:"在多个事务中乐观地读取数据,在提交时再验证是否有冲突,如果没有,则提交;如果有,则回…

每天五分钟深度学习:向量化技术在神经网络中的应用

本文重点 向量化技术,简而言之,就是利用矩阵运算(而非传统的for循环)来执行大规模的计算任务。这种技术依赖于单指令多数据(SIMD)架构,允许一个指令同时对多个数据元素执行相同的操作。例如,在向量化加法中,不再需要逐个元素进行加法操作,而是可以一次性对整个向量执…

Android使用AndServer在安卓设备上搭建服务端(Java)(Kotlin)两种写法

一直都是通过OkHttp远程服务端进行数据交互,突发奇想能不能也通过OkHttp在局域网的情况下对两个安卓设备或者手机进行数据交互呢? 这样一方安卓设备要当做服务端与另一个安卓设备通过OkHttp进行数据交互即可 当然还可以通过 socket 和 ServerSocket 通…

EasyExcel批量读取Excel文件数据导入到MySQL表中

1、EasyExcel简介 官网&#xff1a;EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 2、代码实战 首先引入jar包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</v…

PMP–知识卡片--项目管理五大过程组

记忆 五大“项目管理过程组”&#xff1a;启动&#xff0c;规划&#xff0c;执行&#xff0c;监控&#xff0c;收尾 五个领域&#xff0c;十个字&#xff0c;形象理解&#xff0c;理解逻辑&#xff1a;先启动→再规划→再执行→要监控→最后收尾 定义 经典项目管理场景将项目…

“闭门造车”之多模态思路浅谈:自回归学习与生成

©PaperWeekly 原创 作者 | 苏剑林 单位 | 科学空间 研究方向 | NLP、神经网络 这篇文章我们继续来闭门造车&#xff0c;分享一下笔者最近对多模态学习的一些新理解。 在前文《“闭门造车”之多模态思路浅谈&#xff1a;无损》中&#xff0c;我们强调了无损输入对于理想的…

mac生成.dmg压缩镜像文件

mac生成.dmg压缩镜像文件 背景准备内容步骤1&#xff0c;找一个文件夹2&#xff0c;制作application替身1&#xff0c;终端方式2&#xff0c;黄金右手方式 3&#xff0c;.app文件放入文件夹4&#xff0c;制作.dmg压缩镜像文件5&#xff0c;安装.dmg 总结 背景 为绕开App Store…

Go语言---并发编程之channel(双channel,单channel)以及应用实例(生产者消费者、打印机模型)

Channel goroutine 运行在相同的地址空间&#xff0c;因此访问共享内存必须做好同步。goroutine 通过通信来共享内存&#xff0c;而不是其享内存来通信。 引用类型 channel 是CSP 模式的具体实现,用于多个 goroutine 通讯。其内部实现了同步&#xff0c;确保并发安全。 chan…

FastAPI 学习之路(三十四)数据库多表操作

之前我们分享的是基于单个表的数据库表的操作&#xff0c;我们在设计数据库的时候也设计了跨表&#xff0c;我们可以看下数据库的设计 class User(Base):__tablename__ "users"id Column(Integer, primary_keyTrue, indexTrue)email Column(String(10), uniqueTr…

Python:Python基础知识(注释、命名、数据类型、运算符)

.注释 Python有两种注释方法&#xff1a;单行注释和多行注释。单行注释以#开头&#xff0c;多行注释以三个单引号 或三个双引号 """ 开头和结尾。 2.命名规则 命名规则: 大小写字母、数字、下划线和汉字等字符及组合&#xff1b; 注意事项: 大小写敏感、首…