Solved

Destroying non-modal Dialog Boxes.

Posted on 1998-08-17
9
415 Views
Last Modified: 2010-04-10
The Compiler is generating a warning regarding the destruction of a non-modal window.  The window itself pops up while the application is processing a task that could be lengthy.  During the processing, it increments a Progress Bar on the non-modal Dialog Box, then a call to DestroyWindow() closes the window.  When the application launches and I view the Debug notes in Developer Studio, I see the following warning:

Warning: calling DestroyWindow in CDialog::~CDialog --
      OnDestroy or PostNcDestroy in derived class will not be called.

I have tried destroying the window in the Destructor of the Class that governs the Dialog Box, but the warning was still generated.  Any idea why this is, and what I can do to prevent it?
0
Comment
Question by:MFC
  • 5
  • 3
9 Comments
 
LVL 1

Expert Comment

by:alex_r
ID: 1170579
Try to change the call to DestroyWindow() with the following:

dialog->PostMessage(WM_CLOSE);
0
 

Author Comment

by:MFC
ID: 1170580
Replacing the call to DestroyWindow() with [dialog]->PostMessage(WM_CLOSE) did not correct the problem.  I think that the error is not generated by the call to DestroyWindow but rather how my Derived Class (called CRouteProgress) is defined.  The actual Dialog Box is neither launched nor destroyed within the Constructor/Destructor of the Class itself, but rather from within a function in MainFrm.cpp.  Other functions within my application post a message, which causes the proper function in MainFrm to execute.  There are three possible messages corresponding to three possible calls: Create (launch) the window, increment the Progress Bar, and Destroy (close) the window.  Those messages can be posted any time from any function, so I am deliberately launching and closing the window, rather than allowing it to simply fall out of scope and close itself in the Destructor.

Anyway, thanks for the response.  I'll keep working on it...
0
 
LVL 23

Accepted Solution

by:
chensu earned 100 total points
ID: 1170581
The warning is saying that the dialog box window has not been destroyed when the execution reaches CDialog::~CDialog, so it calls DestroyWindow in it for you.

You should PostMessage(WM_CLOSE) before the dialog box object is released. Don't call PostMessage(WM_CLOSE) in the destructor of the dialog box class. How do you allocate the dialog box object? If it is allocated on the stack, the destructor may be called before the dialog box is actually destroyed.

{
CDialog dlg;
.
dlg.PostMessage(WM_CLOSE);
// dlg's destructor is going to be called before the dialog box window is destroyed.
}

You may define dlg as a member variable of the parent window class.

0
 

Author Comment

by:MFC
ID: 1170582
The Header file for the Class is included within Mainfrm.h, then the Object is created within the Public section of the CMainFrame Class.  The Object is declared as a Public pointer of CMainFrame, like this: CRouteProgress* m_pRoutingProgress;.  Then, the Object itself is created when the calling function posts a message to the Main thread.  That same function, after calling many other functions and performing various types of processing, posts another message to destroy the window.  Both launch and close are handled within the Main thread, triggered by messages posted from another thread.  I am not calling PostMessage(WM_CLOSE) in the destructor of the dialog box class.  Rather, I am calling DestroyWindow() directly after the message is posted to the Main thread (i.e., the Main thread sees a message posted to it, then calls the corresponding function, which calls DestoryWindow).  The objective is to launch the window when a function begins execution, then close it when that function completes its processing.  Because any function within any thread of the application may need this capability, the generic window is controlled within the Main thread and all others post to that thread to govern the window.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 23

Expert Comment

by:chensu
ID: 1170583
Show the relevant code.
0
 

Author Comment

by:MFC
ID: 1170584
Here's the Header file for the Class:

#include "afxcmn.h"                              // For support of Progress Bar

/////////////////////////////////////////////////////////////////////////////
// CRouteProgress dialog

class CRouteProgress : public CDialog
{
// Construction
public:
  CRouteProgress(CWnd* pParent = NULL);   // std const.
  ~CRouteProgress();   // standard destructor
  CRouteProgress* m_pRoutingProgress;     // My Object

// Dialog Data
  //{{AFX_DATA(CRouteProgress)
  enum { IDD = IDD_ROUTE_PROGRESS };
  CProgressCtrl      m_RouteProgress;
  //}}AFX_DATA


// Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CRouteProgress)
  protected:
  virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV
  //}}AFX_VIRTUAL

// Implementation
protected:

  // Generated message map functions
  //{{AFX_MSG(CRouteProgress)
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}

-----------------------------------------------------------
Here's the actual Source Code for the Class:
#include "stdafx.h"
#include "synergy2.h"
#include "RouteProgress.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CRouteProgress dialog


CRouteProgress::CRouteProgress(CWnd* pParent /*=NULL*/)
      : CDialog(CRouteProgress::IDD, pParent)
{
      //{{AFX_DATA_INIT(CRouteProgress)g
      //}}AFX_DATA_INIT
}

CRouteProgress::~CRouteProgress()
{
}

void CRouteProgress::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CRouteProgress)
      DDX_Control(pDX, IDC_ROUTE_PROGRESS, m_RouteProgress);
      //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CRouteProgress, CDialog)
      //{{AFX_MSG_MAP(CRouteProgress)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRouteProgress message handlers

-----------------------------------------------------------
This is message handling in MainFrm.CPP:

//  ______________________________________________________
// | Function Name: OnRoutingStatus                       |
// |______________________________________________________|

LRESULT CMainFrame::OnRoutingStatus(WPARAM WParam, LPARAM LParam)
{
  m_pRoutingProgress=new CRouteProgress;        
  if (m_pRoutingProgress)
  {
    m_pRoutingProgress->Create(IDD_ROUTE_PROGRESS,NULL);
    m_pRoutingProgress->m_RouteProgress.StepIt();
  }
  return 0;
}
//  ______________________________________________________
// | Function Name: OnRoutingStatusClose                  |
// |______________________________________________________|

LRESULT CMainFrame::OnRoutingStatusClose(WPARAM WParam, LPARAM LParam)
{
  if (m_pRoutingProgress)
  {
    m_pRoutingProgress->PostMessage(WM_CLOSE);
    delete m_pRoutingProgress;
  }
  return 0;
}
//  ______________________________________________________
// | Function Name: OnRoutingStatusIncrement              |
// |______________________________________________________|

LRESULT CMainFrame::OnRoutingStatusIncrement(WPARAM WParam, LPARAM LParam)
{
  if (m_pRoutingProgress)                        
    m_pRoutingProgress->m_RouteProgress.StepIt();
  return 0;
}

---------------------------------------------------------
This is how the dialog is launched from within other functions:
if (lpMainWindow && ::IsWindow(lpMainWindow->m_hWnd))
  ::PostMessage(lpMainWindow->m_hWnd, WM_ROUTE_STATUS, 0, 0);

This is how the dialog is closed from within other functions:
if (lpMainWindow && ::IsWindow(lpMainWindow->m_hWnd))
  ::PostMessage(lpMainWindow->m_hWnd, WM_ROUTE_STATUS_CLOSE,  
                0, 0);
0
 

Author Comment

by:MFC
ID: 1170585
One correction:

The Message Handler in MainFrm.CPP that closes the window actually looks like this:

LRESULT CMainFrame::OnRoutingStatusClose(WPARAM WParam, LPARAM LParam)
{
  if (m_pRoutingProgress)  
  {
    m_pRoutingProgress->DestroyWindow();
    delete m_pRoutingProgress;
  }
  return 0;
}

The first one that I showed was experimental and I forgot to roll it back prior to posting it for you.  Sorry 'bout 'dat.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1170586
The problem is,

m_pRoutingProgress->DestroyWindow();
// The window may not be destroyed immediately.
delete m_pRoutingProgress;  // The destructor is called.


Put "delete m_pRoutingProgress;" in the CMainFrame::~CMainFrame() and "m_pRoutingProgress=new CRouteProgress;" in the CMainFrame::CMainFrame(). Or, define a member variable CRouteProgress m_RoutingProgress instead of creating it dynamically.
0
 

Author Comment

by:MFC
ID: 1170587
I will implement your suggestion.  Thanks for your help.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

747 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

10 Experts available now in Live!

Get 1:1 Help Now