目录
引言
一、对话框简介
1.1 对话框的创建
1.2 基本函数
1.3 模态对话框与非模态对话框
1.4 对话框与窗口的区别
二、模态对话框编程方法
2.1 模态对话框编程
2.2 消息框
三、非模态对话框编程方法
四、综合代码案例
引言
在Windows应用程序开发中,对话框是用户交互的重要组件,能够简化复杂界面的设计和实现。通过资源编辑器,开发者可以快速创建对话框资源,并通过`DialogBox`或`CreateDialog`函数将其集成到应用程序中。模态对话框要求用户先关闭对话框才能操作主窗口,而非模态对话框则允许用户同时与主窗口和对话框交互。无论是简单的消息框还是复杂的自定义对话框,Windows提供了丰富的API和资源管理机制,帮助开发者高效构建用户友好的界面。
一、对话框简介
1.1 对话框的创建
虽然可以使用 `CreateWindow` 创建 `POPUP` 风格的窗口,但对话框程序通常包含多个控件,逐个创建控件会非常繁琐。因此,微软提供了更为便捷的方式来创建对话框程序。
通过资源编辑器,我们可以直接创建对话框资源,并通过资源 ID 来标识。在对话框上,可以拖拽各种控件(如 `Button`、`Edit`、`Static` 等),并通过属性调整对话框和控件的风格。随后,调用 `DialogBox` 或 `CreateDialog` 函数,利用资源创建出对话框。
在资源视图中,右键单击 `.rc` 文件,选择“添加资源”,然后新建一个对话框,即可创建对话框资源。通过“视图 -> 工具箱”可以向对话框上添加控件。
1.2 基本函数
常用的对话框创建函数有两个:
INT_PTR WINAPI DialogBox(_In_opt_ HINSTANCE hInstance,_In_ LPCTSTR lpTemplate,_In_opt_ HWND hWndParent,_In_opt_ DLGPROC lpDialogFunc
);HWND WINAPI CreateDialog(_In_opt_ HINSTANCE hInstance,_In_ LPCTSTR lpTemplate,_In_opt_ HWND hWndParent,_In_opt_ DLGPROC lpDialogFunc
);
- `DialogBox`:用于生成模态窗口。
- `CreateDialog`:用于创建非模态窗口。
两者都会调用 `CreateWindow` 来创建窗口。非模态对话框需要程序员自己实现消息循环,而模态对话框自带消息循环,消息循环在函数内部进行。退出模态对话框需要使用 `EndDialog`。
参数对比:
`DialogBox` 和 `CreateDialog` 的参数相同:
(1)当前程序实例句柄
(2)资源 ID
(3)父实例句柄(通常为空)
(4)回调函数指针(需要用 `DLGPROC` 转换)
两者的主要区别在于模态与非模态,`CreateDialog` 的消息循环需要程序员自己实现。
1.3 模态对话框与非模态对话框
- 模态对话框:创建后,用户必须关闭对话框,父窗口才能响应用户操作。否则,父窗口无法响应任何用户操作。
- 非模态对话框:创建后,父窗口不需要等待对话框关闭即可响应用户操作,即使对话框未关闭,父窗口仍可响应用户操作。
1.4 对话框与窗口的区别
对话框处理的主要消息:
- `WM_INITDIALOG`:对话框初始化时执行的操作。
- `WM_COMMAND`:响应对话框上控件的操作。
- `WM_NOTIFY`:响应对话框上控件的复杂操作。
二、模态对话框编程方法
2.1 模态对话框编程
(1)定义对话框资源
在资源中添加一个对话框,并拖拽一些控件。
(2)调用 `DialogBox` 显示对话框
定义资源后,调用 `DialogBox` 函数显示对话框:
int DialogBox(HINSTANCE hInstance, LPCTSTR lpszDialogName, HWND hwnd, WNDPROC lpDialogFunc);
(3)构造对话框消息处理函数
对话框消息处理函数的一般形式:
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {switch(message) {case WM_INITDIALOG: return 1;case WM_COMMAND:switch(LOWORD(wParam)) {case ...: break;case ...: break;}break;...}return 0;}
在消息处理函数中,主要处理以下两类消息:
- `WM_INITDIALOG`:对话框初始化时执行的操作。
- `WM_COMMAND`:响应对话框上控件的操作。
(4)关闭对话框函数
在消息处理函数中调用 `EndDialog` 关闭对话框。
2.2 消息框
消息框是模态对话框的一种特殊形式。应用程序可以通过调用 `MessageBox` 函数快速生成一些简单但常用的 Windows 消息框。函数原型为:
int MessageBox(HWND hwnd, LPCTSTR lpszText, LPCTSTR lpszCaption, DWORD dwType);
- `hwnd`:拥有该消息的窗口。
- `lpszText`:消息框中显示的字符串。
- `lpszCaption`:作为标题的字符串。
- `dwType`:指定消息框的内容。
常用标识及说明:
用户操作与 `MessageBox` 返回值的对应关系:
三、非模态对话框编程方法
(1)定义对话框资源
与非模态对话框相同。
(2)创建对话框
非模态对话框的创建由 `CreateDialog` 函数完成:
HWND CreateDialog(HINSTANCE hInstance, LPCTSTR lpszDialogName, HWND hwndParent, WNDPROC lpDialogFunc);
(3)消息循环部分的处理
由于非模态对话框不禁止应用程序向其他窗口发送消息,因此在 `WinMain` 函数的消息循环中,必须包含截获发往非模态对话框的消息,并将其发往相应的对话框处理函数处理。消息循环的一般形式为:
while (GetMessage(&Msg, NULL, 0, 0)) {if (!IsDialogMessage(hdlg, &Msg)) {TranslateMessage(&Msg);DispatchMessage(&Msg);}}
(4)关闭对话框函数
在消息处理函数中调用 `DestroyWindow` 关闭对话框:
BOOL DestroyWindow(HWND hwnd);
四、综合代码案例
以下是一个综合性的C++代码案例,展示了如何在Windows应用程序中使用模态对话框和非模态对话框。代码包括创建对话框、处理对话框消息、使用消息框等功能。
完整代码示例
#include <windows.h>
#include <string>
#include "resource.h"// 函数前向声明
INT_PTR CALLBACK ModalDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK ModelessDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);// 全局变量
HWND g_hModelessDialog = NULL; // 非模态对话框句柄// 主对话框过程函数
INT_PTR CALLBACK MainDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) {case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:switch (LOWORD(wParam)) {case IDC_BUTTON_OPEN_MODAL:// 调用模态对话框DialogBox((HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE),MAKEINTRESOURCE(IDD_MODAL_DIALOG),hDlg, ModalDialogProc);break;case IDC_BUTTON_OPEN_MODELESS:// 调用非模态对话框if (!g_hModelessDialog) {g_hModelessDialog = CreateDialog((HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE),MAKEINTRESOURCE(IDD_MODELESS_DIALOG),hDlg, ModelessDialogProc);ShowWindow(g_hModelessDialog, SW_SHOW);}break;case IDC_BUTTON_CLOSE:// 关闭主对话框EndDialog(hDlg, LOWORD(wParam));break;}break;case WM_DESTROY:if (g_hModelessDialog) {DestroyWindow(g_hModelessDialog); // 关闭非模态对话框}break;}return (INT_PTR)FALSE;
}// 模态对话框过程函数
INT_PTR CALLBACK ModalDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) {case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {// 关闭模态对话框EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;
}// 非模态对话框过程函数
INT_PTR CALLBACK ModelessDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) {case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDCANCEL) {// 关闭非模态对话框DestroyWindow(hDlg);g_hModelessDialog = NULL;return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;
}// 应用程序入口函数
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {// 显示主对话框DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, MainDialogProc);return 0;
}
资源文件(`.rc`文件)
在资源文件中定义对话框和控件:
#include <windows.h>
#include <winres.h>
#include <commctrl.h>
#include "resource.h"// 主对话框资源
IDD_MAIN_DIALOG DIALOGEX 0, 0, 200, 100
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION L"主对话框"
FONT 9, "Microsoft YaHei"
BEGINDEFPUSHBUTTON L"打开模态对话框", IDC_BUTTON_OPEN_MODAL, 10, 10, 120, 20PUSHBUTTON L"打开非模态对话框", IDC_BUTTON_OPEN_MODELESS, 10, 40, 120, 20PUSHBUTTON L"关闭", IDC_BUTTON_CLOSE, 10, 70, 120, 20
END// 模态对话框资源
IDD_MODAL_DIALOG DIALOGEX 0, 0, 150, 80
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION L"模态对话框"
FONT 9, "Microsoft YaHei"
BEGINPUSHBUTTON L"确定", IDOK, 30, 40, 80, 20PUSHBUTTON L"取消", IDCANCEL, 30, 70, 80, 20
END// 非模态对话框资源
IDD_MODELESS_DIALOG DIALOGEX 0, 0, 150, 80
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION L"非模态对话框"
FONT 9, "Microsoft YaHei"
BEGINPUSHBUTTON L"关闭", IDCANCEL, 30, 40, 80, 20
END
头文件(`resource.h`)
定义资源ID:
#ifndef RESOURCE_H
#define RESOURCE_H#define IDD_MAIN_DIALOG 101
#define IDD_MODAL_DIALOG 102
#define IDD_MODELESS_DIALOG 103// Control IDs
#define IDC_BUTTON_OPEN_MODAL 104
#define IDC_BUTTON_OPEN_MODELESS 105
#define IDC_BUTTON_CLOSE 106 #endif // RESOURCE_H
代码说明
(1)主对话框:
- 包含三个按钮:打开模态对话框、打开非模态对话框、关闭主对话框。
- 点击“打开模态对话框”按钮,弹出模态对话框。
- 点击“打开非模态对话框”按钮,弹出非模态对话框。
- 点击“关闭”按钮,关闭主对话框。
(2)模态对话框:
- 包含“确定”和“取消”按钮。
- 点击按钮后关闭对话框。
(3)非模态对话框:
- 包含“关闭”按钮。
- 点击按钮后关闭对话框。
(4)全局变量:
- `g_hModelessDialog` 用于保存非模态对话框的句柄。
(5)消息循环:
- 主对话框使用 `DialogBox` 创建,自带消息循环。
- 非模态对话框使用 `CreateDialog` 创建,需要主对话框的消息循环处理非模态对话框的消息。
运行效果
1. 主对话框显示后,点击“打开模态对话框”按钮,弹出模态对话框。在模态对话框关闭之前,主对话框无法响应操作。
2. 点击“打开非模态对话框”按钮,弹出非模态对话框。非模态对话框和主对话框可以同时操作。
3. 点击“关闭”按钮,关闭主对话框。
通过这个案例,您可以掌握如何在Windows应用程序中使用模态对话框、非模态对话框以及消息框。