MS documentation(和others)“明确地”指出:

...因为CDialog的常规OnOk和OnCancel成员函数
对象将调用EndDialog,请确保您的无模式对话框
不调用这些函数,而是覆盖

由于CDialog::OnOk有效调用CDialog::EndDialog,因此该方法如下所示:

void CDialog::EndDialog(int nResult)
{
    ASSERT(::IsWindow(m_hWnd));

    if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL))
        EndModalLoop(nResult);

    ::EndDialog(m_hWnd, nResult);
}

我们还可以检查the docs for ::EndDialog 再次“清楚地”状态:

由DialogBox创建的对话框,DialogBoxParam,
DialogBoxIndirect和DialogBoxIndirectParam函数必须为
使用EndDialog函数销毁。应用程序调用EndDialog
从对话框过程中;该功能不得使用
用于其他目的。

但是,我有一个CDialog派生类,它具有默认行为wrt。 OnOK,当我以非模态/非模态方式使用它时,似乎一切正常。

那是:
*当我关闭(无模式)对话框时,它是关闭的/从 View 中删除的。
*该应用程序不显示任何内存泄漏。 (MFC调试版本)

所以呢?是否需要阻止EndDialog并自己调用DestroyWindow

注意:我知道文档和“网络”怎么说。只是我还没有找到为什么我需要做不同的事情,而这一类应该可用于无模式和模态模式,因此不必做任何不同的事情可能会很方便。

最佳答案

CDialog::OnOKMSDN Docs明确指出

如果在无模式对话框中实现“确定”按钮,则必须
覆盖OnOK方法并在其中调用DestroyWindow。不要打电话
基本类方法,因为它调用EndDialog,这使得
对话框不可见但不会破坏它

因此,您需要重写CDialog::OnOK并在其中调用DestroyWindow(),这是MSDN的修改示例:

class CDlg : public CDialog
{
    ...
    BOOL m_bModal;
    ...
}

CDlg::CDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDlg::IDD, pParent)
{
    ...
    m_bModal = FALSE;
    ...
}

INT_PTR CDlg::DoModal()
{   m_bModal = TRUE;
    const INT_PTR rval = CDialog::DoModal();
    m_bModal = FALSE;
    return rval;
}

void CDlg::OnOK()
{
   if (!UpdateData(TRUE))
   {
      TRACE(_T("UpdateData failed during dialog termination\n"));
      // The UpdateData routine will set focus to correct item
      return;
   }
   if (m_bModal)
       EndDialog(IDOK);
   else
       DestroyWindow();
}

void CDlg::OnCancel()
{
   if (m_bModal)
       EndDialog(IDCANCEL);
   else
       DestroyWindow();
}

09-17 11:08