模态对话框与非模态对话框(modeless)

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。

你可能感兴趣的:(MFC)