对话框
见钱眼开 于
2005-6-4
对话框的一般形式是包含多种子窗口控件的弹出式窗口,这些控件的大小和位置在资源描述文件“对话框模板”中指定。
一般来说,除了在创建对话框时初始化子窗口控件,处理来自子窗口控件的消息以及结束对话框外,不需要再给对话框过程增加其他功能。对话框过程通常不处理
WM_PAINT消息,也不处理键盘和鼠标消息。
对话框分两类:“模态的”和“非模态的”。显示模态对话框时,关闭该对话框前无法切换到同一程序的另一个窗口。
以下是资源描述文件中的一个“对话框模板”:
ABOUTBOX DIALOG DISCARDABLE 32, 32, 180, 100
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON
"OK",IDOK,66,80,50,14
ICON
"ABOUT1",IDC_STATIC,7,7,21,20
CTEXT
"About1",IDC_STATIC,40,12,100,8
CTEXT
"About Box Demo Program",IDC_STATIC,7,40,166,8
CTEXT
"(c) Charles Petzold, 1998",IDC_STATIC,7,52,166,8
END
“
EGIN”和“END”语句之间定义出现在对话框中的子窗口控件。其格式如下:
ControlType "text" id, xPos, yPos, xWidth, yHeight, iStyle
对话框的对话框过程并非对话框实际的窗口过程,只是
Windows内部定义的窗口过程调用对话框过程而已。
BOOL ALLBACK AboutDlgProc (HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam);
窗口过程返回一个
LRESULT;对话框返回一个BOOL。
窗口过程不处理某个消息,那么将交给
DefWindowProc;如果对话框过程不处理某个消息,返回FALSE即可。
对话框过程无需处理
WM_PAINT消息或WM_DESTROY消息。对话框过程不接收WM_CREATE消息;而是在特殊的WM_INITDIALOG消息期间,对话框过程执行初始化操作。
WM_INITDIALOG消息是对话框接收到的第一个消息,这个消息只发送给对话框过程。如果对话框过程返回
TRUE,那么Windows将输入焦点定位到对话框中第一个具有WS_TABSTOP风格的子窗口控件。另外,也可以使用SetFocus将输入焦点定位到某个子窗口控件,然后传回FALSE。
DialogBox函数用于载入对话框模板,并创建一个对话框实例:
INT_PTR nResult = DialogBox(hInstance,TEXT(“AboutBox”),hWnd,AboutDlgProc);
EndDialog函数结束对话框:
EndDialog(hDlg,nResult);
EndDialog函数的第二个参数作为
DialogBox函数返回值返回。
对于模态对话框最常用的风格是
WS_POPUP和DS_MODALFRAME两种。当然我们可以尝试其他风格。例如,WS_CAPTION风格使对话框显示标题栏;WS_SYSMENU风格使对话框拥有系统菜单;WS_THICKFRAME风格允许对话框缩放。
给对话框添加一个菜单,在对话框模板中包括:
MENU menu-name
“menu-name”既是菜单名称,又资源描述中的菜单号。
还可以自定义对话框窗口过程,在对话框模板中指定一个窗口类:
CLASS “class-name”
如果不希望在资源描述文件中定义对话框模板,也可以在运行时调用
DialogBoxIndirect动态创建对话框。
对于子窗口控件,最常用的风格是
WS_CHILD和WS_VISIBLE两种。其他扩充风格详见下表:
控件类型
|
窗口类
|
风格
|
PUSHBUTTON
|
按钮
|
BS_PUSHBUTTON | WS_TABSTOP
|
DEFPUSHBUTTON
|
按钮
|
BS_DEFPUSHBUTTON | WS_TABSTOP
|
CHECKBOX
|
按钮
|
BS_CHECKBOX | WS_TABSTOP
|
RADIOBUTTON
|
按钮
|
BS_RADIOBUTTON | WS_TABSTOP
|
GROUPBOX
|
按钮
|
BS_GROUPBOX | WS_TABSTOP
|
LTEXT
|
静态文字
|
SS_LEFT | WS_GROUP
|
CTEXT
|
静态文字
|
SS_CENTER | WS_GROUP
|
RTEXT
|
静态文字
|
SS_RIGHT | WS_GROUP
|
ICON
|
静态图标
|
SS_ICON
|
EDITTEXT
|
编辑
|
ES_LEFT | WS_BORDER | WS_TABSTOP
|
SCROLLBAR
|
滚动条
|
SBS_HORZ
|
LISTBOX
|
清单方块
|
LBS_NOTIFY | WS_BORDER | WS_VSCROLL
|
COMBOBOX
|
下拉式清单方块
|
CBS_SIMPLE | WS_TABSTOP
|
按下
Tab键实现控件之间切换输入焦点。在对话框中Windows已经完成了所有工作。尽管如此,必须在对话框模板中指定WS_TABSTOP和WS_GROUP风格;对于想要使用Tab键访问的控件必须都指定WS_TABSTOP风格。
通常不包含
WS_TABSTOP风格的控件(特别是静态控件)不应该取得输入焦点。
包含
WS_GROUP风格可实现控件分组。一组指定WS_GROUP风格的单选按钮,使用光标移动键,可以将输入焦点从当前单选按钮移动到组内其它单选按钮上。缺省设置下,控件LTEXT、CTEXT、RTEXT、ICON包含有WS_GROUP风格。
Windows提供了两个函数,以便查找下一个或者前一个
Tab键停留项或者组项。这些函数为:
hwndCtrl = GetNextDlgTabItem (hDlg, hwndCtrl, bPrevious) ;
hwndCtrl = GetNextDlgGroupItem (hDlg, hwndCtrl, bPrevious) ;
如果
bPrevious为TRUE,那么函数返回前一个Tab键停留项或组项;如果为FALSE,则返回下一个Tab键停留项或者组项。
模态对话框是用
DialogBox创建的。只有在关闭对话框之后,函数才会返回值。在对话框过程内调用EndDialog终止对话框,并且DialogBox返回该函数的第二个参数值。非模态对话框是用CreateDialog创建的,该函数所使用的参数与DialogBox相同。
hDlgModeless = CreateDialog (hInstance,szTemplate,hwndParent,DialogProc) ;
区别是
CreateDialog函数立即返回对话框窗口句柄。
模态对话框与非模态对话框的区别:
l 非模态对话框通常包含一个标题栏和一个系统菜单。
l 创建非模态对话框如果未指定
WS_VISIBLE风格,那么调用CreateDialog后必须调用ShowWindow,否则对话框不会显示。
ShowWindow(hDlgModeless,SW_SHOW);
l 与模态对话框消息不同,非模态对话框的消息要经过程序的消息队列。要将这些消息传送给对话框窗口过程,则必须改变消息队列。方法如下:当您使用
CreateDialog建立非模态对话框时,应该将返回的对话框句柄储存在一个全局变量(如hDlgModeless)中,并将消息循环更改为:
while(GetMessage(&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage (hDlgModeless, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
如果消息是发送给非模态对话框,那么
IsDialogMessage将它发送给对话框窗口过 程,并传回TRUE(非0);否则交给 TranslateMessage和DispatchMessage函数。
l 使用
DestroyWindow而不是EndDialog来结束非模态对话框。
自定义对话框窗口类
WNDCLASS结构的cbWndExtra字段必须设为DLGWINDOWEXTRA。
完成注册窗口类,调用
CreateDialog从资源描述中创建对话框(注册窗口类和资源描述中指定窗口类必须一致):
hwnd = CreateDialog(hInstance,szAppName,0,NULL);
Windows预定义多个通用对话框。
BOOL ChooseFont (LPCHOOSEFONT lpcf); //弹出一个字体对话框
BOOL ChooseColor(LPCHOOSECOLOR lpcc); //弹出一个颜色对话框
BOOL GetOpenFileName(LPOPENFILENAME lpofn); //弹出一个打开文件对话框
BOOL GetSaveFileName(LPOPENFILENAME lpofn); //弹出一个保存文件对话框
HWND FindText(LPFINDREPLACE lpfr); //弹出一个查找文本对话框
HWND ReplaceText(LPFINDREPLACE lpfr); //弹出一个替换文本对话框