Solved

How to create well a Modelles Dialog with MFC?

Posted on 2008-10-11
4
565 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
4 Comments
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 125 total points
Comment Utility
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 125 total points
Comment Utility
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
Comment Utility
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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
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.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

744 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now