您的位置:首页 > 其它

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

2017-05-07 18:40 295 查看
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