#define GRAYED 0x0001 // 灰色
#define INACTIVE 0x0002 // 未激活
#define BITMAP 0x0004 // 位图
#define OWNERDRAW 0x0100 // 自画
#define CHECKED 0x0008 // 已选中
#define POPUP 0x0010 // (内部使用)
#define MENUBARBREAK 0x0020 // 'MENUBARBREAK' keyword (不知何意)
#define MENUBREAK 0x0040 // 'MENUBREAK' keyword (不知何意)
#define ENDMENU 0x0080 // (内部使用)
在POPUP菜单的子项中的最后一个菜单项的fItemFlags会被标以ENDMENU(使用“OR”实现)。这是很重要的,因为弹出式菜单项是可以递归的,可能会有好几级菜单。当菜单递归时,菜单项被按顺序插入其中。应用程序可以通过检查菜单项是否有ENDMENU标志来跟踪这个菜单层次。
4.4 对话框资源
一个对话框被包含在一个单个的资源中,它有一个头,还有一部分重复声明对话框中的每一个控件。头格式如下所示:
[资源头 (type = 5)]
struct DialogBoxHeader {
DWORD lStyle;
DWORD lExtendedStyle; // NT扩展样式
WORD NumberOfItems;
WORD x;
WORD y;
WORD cx;
WORD cy;
[名称或序数] MenuName;
[名称或序数] ClassName;
WCHAR szCaption[];
WORD wPointSize; // 仅当对话框设置了字体时此域才会使用
WCHAR szFontName[]; // 同上
};
lStyle项是一个标准窗口样式,由windows.h文件中的标志组成。对话框的默认样式如下:
WS_POPUP | WS_BORDER | WS_SYSMENU
lExtendedStyle项用来指定扩展窗口样式。当在DIALOG语句或其它可设置的语句中指定了扩展样式,那么它们的值就会被存储在这个双字域中。
标记为“名称或序数”的项与资源文件中其余地方的设置方式相同——存储一个名称或一个序数ID。想前面说的一样,若第一个字节为0xffff,则后面的两个字节就是一个序数ID,否则它(包括第一个字节)就是一个以空字符结束的字符串。空字符串用一个单字的0表示。
wPointSize和szFontName项仅当对话框中包含FONT语句是才会设置。可以通过检查lStyle项确定对话框是否包含字体设置。若lStyle & DS_SETFONT (DS_SETFONT = 0x40)为真,则这两项就会被设置。
每个控件的数据始于一个双字边界(因此在两个控件之间可能会存在填充),它们的格式如下:
struct ControlData {
DWORD lStyle;
DWORD lExtendedStyle;
WORD x;
WORD y;
WORD cx;
WORD cy;
WORD wId;
[名称或序数] ClassId;
[名称或序数] Text;
WORD nExtraStuff;
};
与前面一样,lStyle项是一个标准窗口样式,由windows.h文件中的标志组成。控件的类型由class指定。为节省空间、加速处理,许多通用Windows类型都以一个单字表示。由于UNICODE中0x8000是一个合法字符,类型序数都前置0xffff,根Type和Name域的序数表示方式相似。单字类型如下列表所示:
#define BUTTON 0x8000
#define EDIT 0x8100
#define STATIC 0x8200
#define LISTBOX 0x8300
#define SCROLLBAR 0x8400
#define COMBOBOX 0x8500
lExtendedStyle双字用来指定此控件的扩展样式。扩展样式标志置于CONTROL语句的最后,跟在坐标后面。
控件数据最后的附加信息当前并不使用,但将来可能会被用来存储菜单项信息。通常它的长度为0。
对话框脚本中使用的绝大多数语句都被映射为这些类型(包括它们的样式)。这些样式的值可以在windows.h中找到。所有对话框控件都有默认的WS_CHILD和WS_VISIBLE样式。以下列表为脚本语句使用的默认样式:
语句 默认类型 默认样式
CONTROL None WS_CHILD|WS_VISIBLE
LTEXT STATIC ES_LEFT
RTEXT STATIC ES_RIGHT
CTEXT STATIC ES_CENTER
LISTBOX LISTBOX WS_BORDER | LBS_NOTIFY
CHECKBOX BUTTON BS_CHECKBOX | WS_TABSTOP
PUSHBUTTON BUTTON BS_PUSHBUTTON | WS_TABSTOP
GROUPBOX BUTTON BS_GROUPBOX
DEFPUSHBUTTON BUTTON BS_DEFPUSHBUTTON | WS_TABSTOP
RADIOBUTTON BUTTON BS_RADIOBUTTON
AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX
AUTO3STATE BUTTON BS_AUTO3STATE
AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON
PUSHBOX BUTTON BS_PUSHBOX
STATE3 BUTTON BS_3STATE
EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP
COMBOBOX COMBOBOX None
ICON STATIC SS_ICON
SCROLLBAR SCROLLBAR None
控件文本存储在上面介绍的“名称或序数”域中。
4.5 光标资源
光标资源很像图标资源。它们以成组的格式存储,前置组头。组头也使用固定长度的组件索引,允许随机访问每个单独组件。光标头的结构如下:
[资源头 (type = 12)]
struct CursorHeader {
WORD wReserved; // 当前为0
WORD wType; // 图标 = 2
WORD cwCount; // 组件数量
WORD padding; // 填充数据
};
下一部分对每个组件资源都是重复的,起始于双字边界:
struct ResourceDirectory {
WORD wWidth;
WORD wHeight;
WORD wPlanes;
WORD wBitCount;
DWORD lBytesInRes; // 指向组件
WORD wNameOrdinal;
WORD padding; // 填充数据
};
每个光标组件和图标组件也都相似。不过有一个重要的不同点:光标有一个“热点”,而图标没有。下面是组件的结构:
[资源头 (Type = 1)]
struct CursorComponent {
short xHotspot;
short yHotspot;
}
[单色异或掩码(Monochrome XOR mask)]
[单色异或掩码(Monochrome AND mask)]
这些掩码是拷贝自.cur文件的位图。
(待续)