Pregunta

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. OnOKand 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.

¿Fue útil?

Solución

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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top