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

来源:互联网 发布:美工算平面设计吗 编辑:程序博客网 时间:2024/06/05 22:14

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。

0 0