3

In MFC, for the typical dialog window, when OnOK() is called by MFC, this function calls the EndDialog() function, and somehow the class destructor is called at some point.

Suppose I have a public variable, a string named "test", in the CDialog's class, and in the dialog OK button's onBnClick() event, I set this "test" variable to a value. Then I declare an instance of the dialog, and call DoModal() from my main window's class. I can read from the variable that was set once DoModal() returns, no problem.

void Dialog1::OnBnClickedOk()
{
    test = "The test string has been set.";
    OnOK();
}

void CMainFrame::OnEditTest()
{
    Dialog1 dlg;
    dlg.DoModal();
    MessageBox(dlg.test, L"Main Frm",0);
}

This works, but what if I have a dialog with several fields, and a variable for each field. How can I be sure that I can read all of the values from all the variables before the destructor is called? I checked MSDN, and my understanding is that the OnOK() function calls EndDialog(), and at some point, after EndDialog(), the class destructor is called. I want to always be able to read the values from the variables that were set from the OnBnClick() event, but I don't know exactly when MFC calls the class destructor. Does anyone know when the destructor is called once EndDialog() fires?

Thanks, Blitz

Blitz
  • 33
  • 4

1 Answers1

3

When dlg.DoModal() returns, only its window handles are destroyed.

The destructor is called later when dlg goes out of scope. This part is the same with any C++ class.

In your example, dlg goes out of scope when OnEditTest() returns. So basically you don't have to worry and the compiler will let you know if you make a mistake.

For testing, you can add brackets and force dlg to go out of scope sooner:

void CMainFrame::OnEditTest()
{
    {
        Dialog1 dlg;
        dlg.DoModal();
        MessageBox(dlg.test, L"Main Frm",0);
    }
    //dlg goes out of scope here and ~dlg() is called

    //Next line will obviously not compile:
    MessageBox(dlg.test, L"Main Frm",0); 
}

As a side note, you would have to be more careful if you had declared dlg as a pointer. Because you have to delete the pointer manually, and the pointer could still be accessible after the dlg() is destroyed. But that's not the case here.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • I did not know that simply encapsulating code in brackets would cause it to go out of scope like that, thanks. – Blitz Jul 11 '15 at 08:03
  • So EndDialog is called by a CDialog window when it closes. Per MSDN: "EndDialog does not close the dialog box immediately. Instead, it sets a flag that directs the dialog box to close as soon as the current message handler returns." In my example, Is "the current message handler", the execution thread that owns the method that called DoModal? – Blitz Jul 11 '15 at 08:06
  • @Blitz: Curly braces introduce [block scopes](http://en.cppreference.com/w/cpp/language/scope). This is basic C++ (and C). – IInspectable Jul 11 '15 at 08:08
  • Thanks for the link about block scopes. I am new to C++. – Blitz Jul 11 '15 at 08:10
  • I assume `EndDialog` returns only after dialog is destroyed. Documentation would have made it clear if that wasn't the case. `DoModal` returns after dialog is destroyed. – Barmak Shemirani Jul 13 '15 at 15:48