1. 简单百科
  2. 非模态对话框

非模态对话框

非模态对话框,又称无模式对话框,是指在用户打开此类对话框时,仍然能够操作其他窗口的一种对话框类型。例如,Windows操作系统下的记事本程序中的【查找】对话框即属于非模态对话框。这类对话框的特点是不会独占用户的输入焦点,使得用户能够在处理对话框的同时,与其它用户界面元素进行交互。这一特性显著提升了用户体验。

特征

非模态对话框允许用户在处理该对话框的同时,处理目标对话框。它不会垄断用户的输入,这意味着用户可以一边查找,一边修改文章,从而极大地提高了使用的便利性。相比之下,另一类对话框——模态对话框,则会在打开时阻止用户进行其他对象的操作。

创建与关闭

无模式对话框在创建后,其他窗口仍然可以接受用户输入,类似于一个弹出窗口。创建非模态对话框需要调用`BOOL CDialog::Create(UINT nIDTemplate, CWnd* pParentWnd = NULL)`函数来创建对话框,随后还需调用`BOOL CDialog::ShowWindow(SW_SHOW)`函数使其可见。具体示例代码如下:

```C++

void CYourView::OnOpenDlg(void)

{

// 假设IDD_TEST_DLG为已定义的对话框资源ID

CTestDlg *dlg = new CTestDlg;

dlg-\u003eCreate(IDD_TEST_DLG, NULL);

dlg-\u003eShowWindow(SW_SHOW);

// 不要调用delete dlg;

}

```

需要注意的是,在以上代码中,我们在函数结束时不销毁对话框对象。这是因为如果在此时销毁对象(对象被销毁时窗口也会被销毁),而对话框仍在显示状态,将会导致错误。因此,我们需要考虑何时销毁该对象。一种常见的做法是在对话框退出时由其自行销毁。具体实现方法包括在对话框中重载`OnOK()`和`OnCancel()`函数,分别调用父类的同名函数后,再调用`DestroyWindow()`函数强制销毁窗口。在对话框中映射`WM_DESTROY`消息,并在其消息处理函数中调用`delete this`语句,以删除自身对象。相关的示例代码如下:

```C++

void CTestDlg1::OnOK()

{

CDialog::OnOK();

DestroyWindow();

}

void CTestDlg1::OnCancel()

{

CDialog::OnCancel();

DestroyWindow();

}

void CTestDlg1::OnDestroy()

{

CDialog::OnDestroy();

AfxMessageBox("call delete this");

delete this;

}

```

这种方法的关键在于,在窗口被销毁时,删除自身对象。因此,你可以随时调用`DestroyWindow()`函数,以确保对话框及其对象都被正确地销毁。

另一种方法是通过向父窗口发送消息,请求父窗口销毁对话框。首先,需要定义一个用于通知的消息,然后在对话框中映射`WM_DESTROY`消息,在其消息处理函数中调用消息发送函数通知父窗口。在接收到消息的父窗口中,利用`ON_MESSAGE`宏映射处理消息的函数,并在消息处理函数中删除对话框对象。具体的示例代码如下:

```C++

/* 更改对话框的相关文件 */

CTestDlg2::CTestDlg2(CWnd* pParent /*=NULL*/)

: CDialog(CTestDlg2::IDD, pParent)

{

ASSERT(pParent);

m_pParent = pParent;

//{{AFX_数据_INIT(CTestDlg2)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

}

void CTestDlg2::OnOK()

{

CDialog::OnOK();

DestroyWindow();

}

void CTestDlg2::OnCancel()

{

CDialog::OnCancel();

DestroyWindow();

}

void CTestDlg2::OnDestroy()

{

CDialog::OnDestroy();

m_pParent-\u003ePostMessage(WM_DELETE_DLG, (WPARAM)this);

}

/* 在消息接收窗口中添加消息映射 */

/* 在头文件中添加函数定义 */

afx_msg LONG OnDelDlgMsg(WPARAM wP, LPARAM lP);

/* 添加消息映射代码 */

ON_MESSAGE(WM_DELETE_DLG, OnDelDlgMsg)

/* 实现消息处理函数 */

LONG CMy53_s1View::OnDelDlgMsg(WPARAM wP, LPARAM lP)

{

delete (CTestDlg2*)wP;

return 0;

}

/* 创建对话框 */

void CMy53_s1View::OnTest2()

{

CTestDlg2 *dlg = new CTestDlg2(this);

dlg-\u003eCreate(IDD_TEST_DLG_2);

dlg-\u003eShowWindow(SW_SHOW);

}

```

在这个例子中,我们利用消息机制进行通知和数据传递。这是Windows系统中常见的一种通信方式。

此外,非模态对话框还有一种用途,即在用户在对话框中的输入发生变化时,能够及时地反映到其他窗口。以下代码展示了如何在对话框中输入一段文本,然后将其更新到视图的显示区域内。这也是利用消息进行通知和数据传递的一个实例。

```C++

/* 在对话框中获取数据,并向其他窗口发送消息和数据,将数据指针作为参数发送 */

void CTestDlg2::OnCommBtn()

{

char szOut[30];

GetDlgItemText(IDC_OUT, szOut, sizeof(szOut));

m_pParent-\u003eSendMessage(WM_DLG_NOTIFY, (WPARAM)szOut);

}

/* 在消息接收窗口中 */

/* 映射消息处理函数 */

ON_MESSAGE(WM_DLG_NOTIFY, OnDlgNotifyMsg)

/* 在视图中绘制出字符串m_szOut */

void CMy53_s1View::OnDraw(CDC* pDC)

{

CMy53_s1Doc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native 数据 here

pDC-\u003eTextOut(0, 0, "Display String");

pDC-\u003eTextOut(0, 20, m_szOut);

}

/* 处理通知消息,保存信息并更新显示 */

LONG CMy53_s1View::OnDlgNotifyMsg(WPARAM wP, LPARAM lP)

{

m_szOut = (char*)wP;

Invalidate();

return 0;

}

```

值得注意的是,这种利用消息传递数据的方法对于模态对话框以及其他窗口之间的通信也同样适用。

参考资料

MFC---模态对话框及非模态对话框的弹出过程(对话框).CSDN.2024-09-10

快速入门:掌握模态和非模态对话框设计基础.搜狐网.2024-09-10

7.5 模态对话框与非模态对话框.7.5 模态对话框与非模态对话框.2024-09-10