- 无论是模态对话框还是非模态对话框,都可以直接申请基类CDialog 对象来创建。
窗口创建时的消息和虚函数包括WM_CREATE、WM_INITDIALOG、和PreSubclassWindow等;窗口关闭时的消息和虚函数包括WM_CLOSE、WM_DESTORY、OnOK和 OnCancel等。有些消息是所有窗口通用的,例如,WM_CREATE、WM_CLOSE、WM_DESTORY等。有些消息是对话框专用的回调函数,例如,WM_INITDIALOG消息,以及OnOK和 OnCancel虚函数等。
一、对话框创建过程
WM_CREATE和WM_INITDIALOG都是窗口刚创建时的回调消息,当窗口还未显示出来之前,对窗口作预先处理的回调函数。WM_CREATE是所有窗口通用的创建时回调消息,用于包括对话框、MDI或者SDI等任何窗口的初始化,对应的消息映射函数是OnCreate。可以在该函数中编写代码,在窗口刚创建还未显示时,修改父窗口的属性或者创建内部子窗口(但是不能初始化对话框内部控件)。WM_INITDIALOG是对话框专用消息,最常用来初始化对话框及其内部控件,对应消息映射函数是OnInitDialog。基类函数CDialog::OnInitDialog执行过程将所有对话框资源模板内的控件都创建完毕。因此,可以在该函数中,编写代码来对子窗口作初始化设置。
//创建一个基于对话框的程序,程序名为CTest。
//用OnCreate来初始化窗口
int CTestDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
SetWindowText(_T("在 OnCreate 中修改窗口标题"));
return 0;
}
//用OnInitDialog来初始化窗口
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetWindowText(_T("在 OnInitDialog 中修改窗口标题"));
…
通过两次修改窗口标题,可以判断出 OnCreate 函数的回调时间早于 OnInitDialog。
//在主对话框中加入一个 button 按钮,caption 为“聊天”,ID为“IDC_CHAT”
//为该按钮创建一个对话框,对话框ID为“IDD_CHAT”,并为其创建相应类,类名“CChatDlg”
//双击“聊天”按钮,编写其消息映射
//void CTestDlg::OnChat()
//{
// CChatDlg dlg;
// dlg.DoModal();
//}
//在修改上面两个函数代码,添加一行代码并测试
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetWindowText(_T("在 OnInitDialog 中修改窗口标题"));
GetDlgItem(IDC_CHAT)->EnableWindow(FALSE);
…
测试结果说明,在 OnInitDialog函数中子窗口都已经创建完成,可以任意对子窗口进行初始化操作。而在 OnCreate 函数中,对话框中的控件子窗口还未创建,不可以操作控件窗口。
二、对话框关闭过程
在关闭过程中,可能顺次发生的回调包括WM_SYSCOMMAND消息、WM_CLOSE消息、CDialog::OnCancel虚函数和WM_DESTROY消息等。
当单击标题栏关闭按钮,系统首先触发WM_SYSCOMMAND消息。在WM_SYSCOMMAND消息映射函数中编写代码,实现当单击关闭按钮最小化功能。
//系统最先调用的OnSysCommand消息
void CTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if(nID == SC_CLOSE)
{
ShowWindow(SW_MINMIZE);
return;
}
CDialog::OnSysCommand(nID, lParam);
}
WM_CLOSE消息就是WM_SYSCOMMAND消息在接收WM_CLOSE时的分支消息,或者说WM_CLOSE消息是专门用于接收系统命令中的关闭命令中的消息(当用户单击最大化按钮、最小化按钮、还原按钮、关闭按钮都会触发WM_SYSCOMMAND消息。具体可看MSDN中关于 CWnd::OnSysCommand的说明)。
void CTestDlg::OnClose()
{
ShowWindow(SW_MINMIZE);
//CDialog::OnClose();
}
OnOK函数和 OnCancel 函数。这两个函数一般只在对话框中回调,会掉的原因是单击IDOK和IDCANCEL按钮时触发了WM_COMMAND消息。除此之外,在对话框中按<ESC>键时会 OnOK会发生回调。
void CTestDlg::OnCancel()
{
if(AfsMessageBox("确定要退出吗?", MB_YESNO) == IDYES)
CDialog::OnCancel();
}
void CTestDlg::OnOK()
{
if(AfsMessageBox("确定要退出吗?", MB_YESNO) == IDYES)
CDialog::OnOK();
}
WM_DESTROY的消息映射函数是 OnDestroy函数,这个函数对比以上所有回调函数,是最晚接收到的回调函数。所有以上其他回调函数都发生在对话框消失之前,并且可以取消继续关闭对话框窗口。当窗口视野消失后,OnDestroy 回调函数才到达,而且此时已经不可以取消窗口的关闭过程了。
void CTestDlg::OnDestroy()
{
CDialog::OnDestroy();
AfsMessageBox("OnDestroy:对话框已经消失了!");
}