WIN32汇编语言教程:第05章 使用资源 · 5.4 对话框(3)
函数的各参数说明如下:
● hInstance和lpTemplateName—函数从hInstance参数指定的模块中装入lpTemplateName参数指定的对话框资源,然后显示对话框窗口。例子程序中的lpTemplateName参数用的就是我们定义的DLG_MAIN。
● hWndParent——对话框的父窗口,对话框关闭之前将无法切换到父窗口所属的其他窗口中,例子中用对话框做主窗口,所以父窗口句柄是NULL,在其他程序中使用时,这个参数设置为主窗口的句柄。
● lpDialogFunc——指定了对话框过程的地址,例子程序中是_ProcDlgMain。
● dwInitParam——当做WM_INITDIALOG消息的lParam传给对话框过程,读者可以用它来做自定义的用途。
要结束模态对话框,必须在对话框过程的WM_CLOSE消息中使用EndDialog函数:
invoke EndDialog,hDlg,dwResult
不能使用通常的DestroyWindow函数,参数中的hDlg就是对话框窗口的句柄,dwResult参数是退出时的返回值,这个值最后由DialogBoxParam函数返回到主程序中。
2. 创建非模态对话框
创建非模态对话框的函数是CreateDialogParam,它的参数定义和DialogBoxParam一模一样:
invoke CreateDialogParam,hInstance,lpTemplateName,hWndParent,\ lpDialogFunc,dwInitParam mov hDlg,eax
CreateDialogParam和DialogBoxParam在使用中有几个不同点:
● CreateDialogParam在创建对话框后,会根据对话框模板的风格是否定义了WS_VISIBLE来决定是否显示对话框窗口。如果定义了则显示,没有的话,则程序需要在以后自行调用ShowWindow来显示它;而DialogBoxParam函数不管是否定义了WS_VISIBLE风格都会显示对话框。
● CreateDialogParam在建立对话框窗口后直接返回,返回值是对话框窗口的句柄;而DialogBoxParam要在对话框关闭后才返回,返回值是EndDialog中的dwResult参数。
● 在CreateDialogParam返回后,应用程序在自己的消息循环中获取对话框消息,所以如果要用非模态对话框做程序的主窗口,消息循环的代码还是要写的;而DialogBoxParam是使用Windows为它内建的消息循环。
● 关闭非模态对话框使用DestroyWindow函数,注意在这里不要用EndDialog函数。
3. 对话框过程
Windows在“对话框管理器”——也就是为对话框内建的窗口过程中处理对话框消息,在处理前会首先调用用户定义的对话框过程,程序可以在这里选择是否自行处理某些消息。读者在理解时可以把“对话框管理器”看成是对话框的DefWindowsProc,凡是自己不想处理的消息都由它来处理。
和窗口过程一样,对话框过程是一个“回调”子程序,它由程序定义,Windows来调用,模态对话框和非模态对话框的对话框过程是一样的。
对话框过程和窗口过程的输入参数是一样的,也是:
DialogProc proc hwndDlg,uMsg,wParam,lParam
在程序里面一般编写对话框过程的分支结构如下:
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam mov eax,wMsg .if eax == WM_CLOSE ;模态对话框用EndDialog关闭 ;非模态对话框用DestroyWindow关闭 .elseif eax == WM_INITDIALOG ;初始化代码 .elseif eax == WM_COMMAND ;子窗口控件发送的消息 ;wParam的低16位为子窗口控件ID .elseif eax == WM_XXXX ;处理其他需要处理的消息 .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp
注意对话框过程和普通的窗口过程在使用上有以下区别:
● 窗口过程对应于不同的消息有各种不同含义的返回值,而对话框过程返回BOOL类型的值,返回TRUE表示已经处理了某条消息,返回FALSE表示没有处理。“对话框管理器”代码会根据返回值决定是否继续处理某一条消息(惟一的例外是WM_INITDIALOG消息)。
● 对于不处理的消息,不需要调用DefWindowProc来处理,这事情由“对话框管理器”来做。
“对话框管理器”不会把WM_CREATE消息转发给对话框过程,取而代之,它会以WM_INITDIALOG消息来调用对话框过程,程序可以在这里进行一些初始化的操作,WM_INITDIALOG消息的返回值有点特殊,如果程序想自行设置输入焦点,那么可以用SetFocus函数把输入焦点设置到需要的子窗口控件上,然后返回FALSE;如果返回TRUE的话,那么Windows会自动将输入焦点设置到第一个有WS_TABSTOP的子窗口控件上。
对话框过程在WM_COMMAND消息中处理子窗口控件发送的命令,当用户在对话框中按下了按钮,输入文字或选择复选框等操作时,子窗口控件会向对话框过程发送WM_COMMAND消息,wParam是子窗口控件的ID,如例子程序中处理“退出”按钮的消息,在里面用EndDialog函数关闭对话框。
对话框窗口的标题栏上默认没有定义图标,如果要像普通窗口一样显示一个图标,那么可以像例子程序中那样,在WM_INITDIALOG中用WM_SETICON消息来设置。
5.4.4 在对话框中使用子窗口控件
子窗口控件是一些Windows预定义类,它们实际上就是一个个以对话框为父窗口的子窗口。对于程序员来说,在对话框中使用它们的时候并不需要手工去逐一创建,只需要在对话框中定义就可以了,“对话框管理器”会在初始化对话框的时候,根据定义语句自动建立所有的子窗口。
1. 子窗口控件的定义
子窗口控件定义的一般语法是:
CONTROL 文本,ID,类,风格, x, y,宽度,高度[,扩展风格]
“文本”指控件的初始化值,“ID”是子窗口向对话框过程发送WM_COMMAND中用的ID值,“类”可以是按钮(Button)、静态(Static)、编辑(Edit)、滚动条(ScrollBar)、列表框(ListBox)和组合框(ComboBox),这些类都是Windows系统中已经预定义的,“对话框管理器”在初始化的时候把每一条控件定义语句转换成下面的CreateWindow命令:
invoke CreateWindow,类名,文本,风格,\
x,y,宽度,高度,\
对话框窗口句柄,ID,hInstance,NULL
正因为如此,所有可以用CreateWindow建立的子窗口都可以在资源中定义,只要知道要使用的类和风格就可以了。所以除了上面这些基本的类之外,对话框中还可以使用一些通用控件,如“日期”(SysDateTimePick32)、“月历”(SysMonthCal32)、“热键”(msctls_hotkey32)和“列表”(SysListView32)等,括号内是它们的类名,只要把定义语句的“类”写成对应的名称就可以了。
基于同一个预定义类的控件根据风格属性的不同,外表可能完全不同,如单选钮、复选框和分组框使用的类都是Button类,文本、图标框、位图框和线条等都是Static类。使用CONTROL语句定义的时候可能不是很直观,所以Rc.exe资源编译器允许使用另一种语法来书写控件定义:
控件名称 [文本,] ID,x,y,宽度,高度[,风格][,扩展风格]
这里使用“控件名称”而不是“类”是因为这个名称只是Rc.exe使用的缩写,并不是真正的Windows类的名称,“控件名称”由Rc.exe解释成“类”名,同时为它使用了几种默认的风格,定义语句中风格属性实际上是附加在默认风格上的,表5.4列出了每种控件使用的类和默认属性,除了表中列出的默认属性外,每种控件还被默认定义了WS_CHILD和WS_VISIBLE属性。
表5.4 资源脚本中使用的控件名称
控 件 名 称 | 说明 | 基 于 的 类 | 默认窗口风格 |
PUSHBUTTON | 按钮 | Button | BS_PUSHBUTTON,WS_TABSTOP |
DEFPUSHBUTTON | 默认按钮 | Button | BS_DEFPUSHBUTTON,WS_TABSTOP |
CHECKBOX | 复选框 | Button | BS_CHECKBOX,WS_TABSTOP |
AUTOCHECKBOX | 自动复选框 | Button | BS_AUTOCHECKBOX,WS_TABSTOP |
STATE3 | 3态复选框 | Button | BS_3STATE,WS_TABSTOP |
AUTO3STATE | 自动3态复选框 | Button | BS_AUTO3STATE,WS_TABSTOP |
RADIOBUTTON | 单选钮 | Button | BS_RADIOBUTTON,WS_TABSTOP |
AUTORADIOBUTTON | 自动单选钮 | Button | BS_AUTORADIOBUTTON,WS_TABSTOP |
控 件 名 称 | 说明 | 基 于 的 类 | 默认窗口风格 |
GROUPBOX | 分组框 | Button | BS_GROUPBOX |
SCROLLBAR | 滚动条 | ScrollBar | SBS_HORZ |
CTEXT | 居中文本 | Static | SS_CENTER,WS_GROUP |
LTEXT | 左对齐文本 | Static | SS_LEFT,WS_GROUP |
RTEXT | 右对齐文本 | Static | SS_RIGHT,WS_GROUP |
ICON | 图标框 | Static | SS_ICON |
EDITTEXT | 文本编辑 | Edit | ES_LEFT,WS_BORDER,WS_TABSTOP |
COMBOBOX | 组合框 | ComboBox | CBS_SIMPLE,WS_TABSTOP |
LISTBOX | 列表框 | ListBox | LBS_NOTIFY,WS_BORDER |