MFC相当复杂,就连最基本的模态对话框和非模态对话框,用法也不容易理解,实现原理就更复杂了。
先来说点简单的,
一、模态对话框和非模态对话框都继承自CDialog。
1,模态对话
(1)禁用父窗口;
(2)调用CDialog::DoModal创建对话框,;
(3)调用::EndDialog关闭对话框;
(4)无须指定WS_VISIBLE风格,会自动显示;
(5)生命周期短
2,非模态对话框
(1)不禁用父窗口;
(2)调用CDialog::Create函数创建对话框;
(3)调用::DestroyWindow关闭;
(4)须指定WS_VISIBLE风格才能显示;
(5)生命周期长
注意1,DoModal会根据用户点击不同的按钮返回不同的值,默认就是确定(CDialog::OnOK)或取消按钮(CDialog::OnCancel),返回的值分别为:
#define IDOK 1
#define IDCANCEL 2
当然,我们也可以自定义返回值,通过调用::EndDialog函数,指定返回值,如:
void CLoginDlg::OnCancel()
{
::EndDialog(5);
}
那么单击取消按钮(CDialog::OnCancel)时会返回5。连起来的话,我们可以通过下面代码判断,用户点击了确定还是取消按钮:
步骤1:定义
CLoginDlg LoginDlg;
步骤2:创建并判断点击的按钮
if (LoginDlg.DoModal()==IDOK){
.....
}else{
return false;
}
步骤3:点击确定(OnOK)或取消按钮(OnCancel)后,会调用EndDialog关闭对话框
void CLoginDlg::OnCancel()
{
CDialog::OnCancel();
}
void CLoginDlg::OnOK()
{
CDialog::OnOK();
}
CDialog::OnOK、CDialog::OnCancel源代码
void CDialog::OnOK(){
if (!UpdateData(TRUE)){
TRACE0("UpdateData failed during dialog termination.\n");// the UpdateData routine will set focus to correct item
return;
}
EndDialog(IDOK);
}
void CDialog::OnCancel(){
EndDialog(IDCANCEL);
}
可以看出它们是通过EndDialog关闭对话框并传递相应的值。
注意2,模态对话框是通过DoModal来判断点击的是什么按钮,但是非模态对话框呢?
模态对话框生命周期比较短,打开对话框时,其它窗口都被禁用,关闭时生命周期就结束了,所以创建模态对话框时,用一个临时变量存储对话框对象就可以了(比如上面的CLoginDlg LoginDlg)。
非模态对话框并非通过DoModal创建,因为它被创建后,其它对话框还是可以使用的,所以程序不知道它什么时候关闭的。它的生命周期更长,生命周期过程大概如下:
步骤1:定义 class CEx07aView : public CView
{
private:
CEx07aDialog* m_pDlg;
步骤2:创建对话框对象
CEx07aView::CEx07aView(){
m_pDlg = new CEx07aDialog(this);
}
CEx07aView::~CEx07aView(){
delete m_pDlg; // destroys window if not already destroyed
}
步骤3:如果已经存在,就不再创建
if (m_pDlg->GetSafeHwnd() == 0) {
m_pDlg->Create(); // displays the dialog window
}
步骤4:创建对话框
BOOL CEx07aDialog::Create(){
return CDialog::Create(CEx07aDialog::IDD);
}
步骤5:点击确认或取消按钮,发送相应的参数消息
void CEx07aDialog::OnCancel() // not really a message handler{
m_pView->PostMessage(WM_GOODBYE, IDCANCEL);
}
void CEx07aDialog::OnOK() // not really a message handler{
UpdateData(TRUE);
m_pView->PostMessage(WM_GOODBYE, IDOK);
}
步骤6:根据发送的消息,完成相应的操作,并用DestroyWindow销毁对话框
LRESULT CEx07aView::OnGoodbye(WPARAM wParam, LPARAM lParam){
TRACE("CEx07aView::OnGoodbye %x, %lx\n", wParam, lParam);
TRACE("Dialog edit1 contents = %s\n",(const char*) m_pDlg->m_strEdit1);
m_pDlg->DestroyWindow();
return 0L;
}
非模态对话框相对比较复杂。
(1)在步骤5时,通过PostMessage函数传递消息,而模态对话框中采用DoModal函数返回值来判断点击按钮。
二、CFormView,这是MFC使用无模态对话框的一个典型,但是并不是继承直CDialog,而是CScrollView(继承直CView),但是它却具有CDialog的大多数功能,所以它既是一个View,也算是一个CDialog。