The MS documentation (and others) "clearly" states:
... Because the normal OnOk and OnCancel member functions of a CDialog object would call EndDialog, make sure your modeless dialog box does not call those functions and instead overrides
Since CDialog::OnOk
effectively calls CDialog::EndDialog
, and that method looks like:
void CDialog::EndDialog(int nResult)
{
ASSERT(::IsWindow(m_hWnd));
if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL))
EndModalLoop(nResult);
::EndDialog(m_hWnd, nResult);
}
we can also check the docs for ::EndDialog
which again "clearly" state:
Dialog boxes created by the DialogBox, DialogBoxParam, DialogBoxIndirect, and DialogBoxIndirectParam functions must be destroyed using the EndDialog function. An application calls EndDialog from within the dialog box procedure; the function must not be used for any other purpose.
Yet, I have a CDialog
derived class that has it's default behavior wrt. OnOK
and seemingly everything is working when I use it non-modal / modeless.
That is: * When I close the (modeless) dialog, it is closed/removed from view. * The application doesn't show any memory leaks. (MFC debug build)
So what? Do I need to prevent EndDialog
and call DestroyWindow
myself or not?
Note: I know what the docs and "the web" says. It's just that I haven't yet found why I need to do it differently, and this one class should be usable for modeless and modal mode, so not having to do anything different might be handy.
The MSDN Docs for CDialog::OnOK
clearly states
If you implement the OK button in a modeless dialog box, you must override the OnOK method and call DestroyWindow inside it. Do not call the base-class method, because it calls EndDialog which makes the dialog box invisible but does not destroy it
So you would need to override CDialog::OnOK
and call DestroyWindow()
inside -- here's a modified example from 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();
}