win32模态与非模态对话框
一、模态对话框与非模态对话框的区别
使用DialogBox、DialogBoxIndirect、DialogBoxParam、DialogBoxIndirectParam创建模态对话框时,系统会首先将此模态窗口的父窗口disable掉,然后启动和运行一个消息循环,接受和拆分消息。在EndDialog调用时结束消息循环,设置结束模式对话框的返回值,销毁窗口。
使用CreateDialog、CreateDialogIndirect、CreateDialogParam、CreateDialogIndirectParam创建非模态对话框时,不会在内部启动消息循环,而是创建了非模态对话框之后就立刻返回。需要使用DestroyWindow来销毁对话框。
msdn里对于DialogBoxParam函数实现模态对话框的一些描述,如下所示:
// MSDN Remarks
The DialogBoxParam function uses the CreateWindowEx function to create the dialog box. DialogBoxParam then sends a WM_INITDIALOG message to the dialog box procedure. The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.
When the dialog box procedure calls the EndDialog function, DialogBoxParam destroys the dialog box, ends the message loop, enables the owner window (if previously enabled), and returns the value of the nResult parameter specified by the dialog box procedure when it called EndDialog.
Windows Embedded CE does not support all styles in the DLGTEMPLATE structure. This structure is in the template identified by the lpTemplate parameter*.*
二、模拟实现模态窗口
但是如果需要在win32里直接将一个窗口模态显示,没有找到现成的API,于是只能参照msdn里对以上几个api在模态下执行的操作自己来实现了。
1. 非阻塞的方式实现窗口的模态
void DoModal(HWND hwnd) {
HWND hParentWnd = GetParent(hwnd);
while (hParentWnd != NULL) {
EnableWindow(hParentWnd, FALSE);
hParentWnd = GetParent(hParentWnd);
}
ShowWindow(hwnd, SW_SHOW);
BringWindowToTop(hWnd);
}
void EndModal(HWND hwnd) {
HWND hParentWnd = GetParent(hwnd);
while (hParentWnd != NULL) {
EnableWindow(hParentWnd, TRUE);
hParentWnd = GetParent(hParentWnd);
}
ShowWindow(hwnd, SW_HIDE);
}
2. 阻塞的方式实现窗口的模态
static int nReturnCode = -1; // 退出状态码
static bool isBlocking = false; // 是否阻塞
int BlockDlgDoModal(HWND hWnd) {
isBlocking = TRUE;
DoModal(hWnd);
//消息循环
while (isBlocking) {
MSG msg;
if (!GetMessage(&msg, NULL, 0, 0))
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//退出阻塞,恢复状态
EndModal(hWnd);
return nReturnCode;
}
void BlockDlgEndModal(int nCode) {
nReturnCode = nCode;
isBlocking = FALSE;
PostMessage(NULL, WM_NULL, 0, 0);
}
对话框相关的一些参考链接: