WIN32汇编语言教程:第05章 使用资源 · 5.1 菜单和加速键(2)
编译上述文件使用的makefile文件如下:
NAME = Menu OBJS = $(NAME).obj RES = $(NAME).res LINK_FLAG = /subsystem:windows ML_FLAG = /c /coff $(NAME).exe: $(OBJS) $(RES) Link $(LINK_FLAG) $(OBJS) $(RES) .asm.obj: ml $(ML_FLAG) $< .rc.res: rc $< clean: del *.obj del *.res
为了编译资源文件,makefile中比以前多了一个资源编译的隐含规则:
.rc.res: rc $<
同时在exe文件的依赖文件中增加了Menu.res文件。
在rc文件中,各种语句使用的是C语言的格式,因为资源编译器Rc.exe根本上就是Visual C++附带的(这一点在第02章中就提及过),所以在定义等值语句的时候用的是#define,包含语句使用#include<文件名>,用到16进制数值的时候并不是用汇编的语法在后面加h,而是用前面加Ox的方法,如1234h写为Ox1234,注释也要用前面加//的方法。这一点在书写的时候一定要注意,以免引起语法错误。
在脚本文件的头部,首先要把MASM32软件包中的resource.h文件包含进来,这个文件中包括了资源定义中很多的预定义值,如窗口属性与加速键的键值等。资源在程序中的引用往往用一个数值来表示,称为资源的ID值,但在定义的时候直接使用数值不是很直观,所以往往用#define语句将数值定义为容易记忆的字符串。
1. 菜单的定义
在资源脚本文件中菜单的定义格式是:
菜单ID MENU [DISCARDABLE] BEGIN 菜单项定义 ... END
“菜单ID MENU [DISCARDABLE]”语句用来指定菜单的ID值和内存属性,菜单ID可以是16位的整数,范围是1~65 535,在Menu.rc文件中,定义的菜单ID是2000h,但菜单ID也可以用字符串表示,如下面的定义:
MainMenu menu begin menuitem ... end
表示菜单的ID是字符串型的“MainMenu”,但这样定义的话,在程序中引用的时候就要用字符串指针代替16进制的菜单ID值,显得相当不便,所以在实际应用中通常使用16进制数值当做菜单ID。
数值型ID的范围限制在1~65 535之间的原因是字符串在内存中的线性地址总是大于10000h,API函数检测参数时发现小于10000h时就可以把它认为是数值型的,大于10000h时就当做字符串指针处理。
menu关键字后面的DISCARDABLE是菜单的内存属性,表示菜单在不再使用的时候可以暂时从内存中释放以节省内存,这是一个可选属性。菜单项的定义语句必须包含在begin和end关键字之内,这两个关键字也可以用花括号{ 和 } 代替。
菜单项目的定义方法有3类:
MENUITEM 菜单文字,命令ID [,选项列表] (用法1) 或 MENUITEM SEPARATOR (用法2) 或 POPUP 菜单文字 [,选项列表] (用法3) BEGIN item-definitions ... END
下面分别就这3类详细说明,用法1定义的是普通菜单项,图5.1中的“字体”与“背景色”等菜单项都是这样定义的,它的组成部分如下:
● 菜单文字——显示在菜单项中的字符串。如果需要字符串中某个字母带下横线,那么可以在字母前面加&符号,如“字体(F)...”就要写成“字体(&F)...”,带下横线的字母可以被系统自动当做快捷键:在这里,当菜单打开的时候按下F键,那么就相当于用鼠标选择了“字体”选项。在同一个弹出菜单中要注意不同的菜单项快捷键应该有所区别。另外,如果要把加速键的提示信息显示在菜单项的右边,如“字体”菜单项中的“Alt+F”字符,可以在两者中间加\t(表示插入一个Tab字符),写为“字体(&F)...\tAlt+F”,这样Tab后面的字符在显示的时候会右对齐。
● 命令ID——用来分辨不同的菜单项。当菜单被选中的时候,Windows会向窗口过程发送WM_COMMAND消息,消息的参数就是这个命令ID。用命令ID可以分辨用户究竟选中了哪个菜单项,所以不同的菜单项应该定义不同的ID值,除非想让两个菜单项的功能相同。
● 选项——用来定义菜单项的各种属性,它可以是下列数值:
CHECKED——表示打上选定标志(对钩)。
GRAYED——表示菜单项是灰化的。
INACTIVE——表示菜单项是禁用的。
MENUBREAK或MENUBARBREAK——表示将这个菜单项和以后的菜单项列到新的列中。
下面做个实验,当把例子中的“详细资料”一句的定义语句改为:
menuitem "详细资料(&D)",IDM_DETAIL,MENUBARBREAK
显示出来的菜单如图5.2所示。“详细资料”以及以后的菜单项都另起一列了!
图5.2 使用MENUBARBREAK的效果
用法2定义的是菜单项之间的分隔线,显然,分隔线是不需要字符串和选项的。
方法3定义的是弹出式菜单,顶层菜单是由多个弹出式子菜单组成的,所以在Menu.rc文件中,主菜单是由“文件”、“查看”和“帮助”3个顺序定义的弹出式菜单组成的,弹出式菜单的定义也可以嵌套,如“查看”菜单中的“工具栏”又是一个弹出式菜单,在嵌套的时候要注意像写C的源程序一样把begin和end(或者{ 和 })正确地配对。popup菜单的选项列表可以是以下的值:
● GRAYED——表示菜单项是灰化的。
● INACTIVE——表示菜单项是禁用的。
● HELP——表示本项和以后的菜单项是右对齐的,如图5.1中的“帮助”菜单。
popup菜单项选中的时候会自动将弹出式菜单弹出来,不需要向程序发送消息,所以在定义的参数中不需要命令ID。
有些选项是可以同时定义的,如果要指定超过一个的选项,中间要用逗号隔开,但是也有些小小的限制:GRAYED和INACTIVE不能同时使用,MENUBREAK和MENUBARBREAK也是不能同时使用的。