[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

How to create well a Modelles Dialog with MFC?

Posted on 2008-10-11
4
Medium Priority
?
582 Views
Last Modified: 2013-11-20
I have a simplest sample to test Modelless Dialog, but Modelless Dialog allways disappear after created

CMainDlg: is main dialog
CModellesDialog : is other dialog

OnButton1: call a CModellesDialog , but CModellesDialog disappear after created!


- This is my simple sample source

void CMainDlg::OnButton1()
{
      // TODO: Add your control notification handler code here
            CModellesDialog dlg;
            dlg.Create(IDD_DIALOG1,NULL);
            dlg.ShowWindow(1);

            AfxMessageBox(".... if remove this AfxmessageBox, dlg modelles will also close");

}

How to keep CModellesDialog concurrent with MainDialog?
0
Comment
Question by:star6868
3 Comments
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 500 total points
ID: 22696394
this is a typical problem:

void CMainDlg::OnButton1()
{
            CModellesDialog dlg;     // Dialog object is constructed
            dlg.Create(IDD_DIALOG1,NULL);     // Dialog object is created
            dlg.ShowWindow(1);  // dialog is shown
}  // Dialog object is destroyed

The problem is that you are instantiating directly the dialog objects at the OnButton1 event.
You can a couple of choices, like:

void CMainDlg::OnButton1()
{
            CModellesDialog  *dlg = new CModellesDialog();     // Dialog object is dynamically constructed
            dlg->Create(IDD_DIALOG1,NULL);     // Dialog object is created
            dlg->ShowWindow(1);   //  dialog is shown
}  // dialog not destroyed

or, put CModelles dlg as a class' member and crete at the OnButton1() event:

void CMainDlg::OnButton1()
{
            /////// CModellesDialog dlg;     // Dialog set as a class member
            dlg.Create(IDD_DIALOG1,NULL);     // Dialog object is created
            dlg.ShowWindow(1);   // dialog is shown
}  // Dialog object is not destroyed


0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 500 total points
ID: 22704908
You should have a class member *pointer* to the modeless dialog.

Otherwise you could create it only once.  

void MyFirstDlg::OnClickedButtonStartModeless()
{
       // don't create the modeless twice
       if (m_pDlgModeLess != NULL) return;

       m_pDlgModeLess = new MyModelessDlg();
       m_pDlgModeLess->Create(IDD_DLG_MODELESS, this);
       m_pDlgModeLess->ShowWindow(SW_SHOW);
 }  

In the destructor of the first dialog you should send a WM_CLOSE message to the modeless dialog in case it is still active. Then you could have a handler for WM_NCDESTROY of the modeless dialog which looks like

void MyModelessDlg::OnNCDestroy()
{
      CWnd* pParent;
      if ((pParent = GetParent()) != NULL)
      {
           // set the member pointer of the parent to NULL
           ((MyFirstDlg*)pParent)->m_pDlgModeLess = NULL;
           // then delete own instance. It is safe cause that is the very last
           // statement for that CWnd instance
           delete this;
      }
}

With the above the user could actively terminate the modeless dialog or it is terminated with the parent dialog:

MyFirstDlg::~MyFirstDlg
{
     if (m_pModelessDlg != NULL)
     {
           m_pModelessDlg->SendMessage(WM_CLOSE);
           Sleep(500);  // wait a little while in case the WM_NCDESTROY
                                // was sent asynchronously
     }
     
}

The Sleep is only for safety. With newer compilers (later than VC6) it shouldn't be necessary.


       
delete the dialog pointer in case it is not already deleted.


0
 
LVL 1

Expert Comment

by:muttley3141
ID: 22715442
You have put your modeless dialog as a local variable inside the handler. This means that when the handler exits (pressing OK on your message box), the local variable goes out of existence, so the dialog's destructor is called.

You need to construct/create your modeless dialog outside your handler, so that it continues to exist when the handler exits.

The way I usually do it is to have a private membervariable of CMainDialog being a pointer to your CModellesDialog.

class CMainDialog
{
..
..
private:
  CModellesDialog *pmd;
..
}

In your constructor, have:
CMainDialog::CMainDialog(...)
{
..
pmd = new CModellesDialog(...)
..
}

In your CMainDialog::OnInitDialog()
CMainDialog::OnInitDialog()
{
  pmd->Create(...);
  pmd->ShowWindow(SW_SHOW);
}

That will give you a modeless dialog that exists for the lifetime of the program.

However, that's probably not what you want. Instead, take out the ShowWindow() line above and put it in as a response to your button-press handler.

You will naturally need two buttons: one to show the dialog and another to hide it.

Doing it this way means that the dialog exists all the time the program does, consuming resources. However, this can be beneficial if you want the dialog to retain state all the time.

You could really have the "pmd" member variable as the Modeless dialog itself, rather than a pointer to it. Then you wouldn't have to do any newing, just creating.

If you don't want a dialog to exist all the time, then you'll have to go through the new/create/delete cycle whenever your button-presses require it.
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Suggested Courses

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question