We help IT Professionals succeed at work.

Destroying non-modal Dialog Boxes.

MFC
MFC asked
on
616 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?
Comment
Watch Question

Commented:
Try to change the call to DestroyWindow() with the following:

dialog->PostMessage(WM_CLOSE);
MFC

Author

Commented:
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...
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
MFC

Author

Commented:
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.

Commented:
Show the relevant code.
MFC

Author

Commented:
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);
MFC

Author

Commented:
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.

Commented:
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.
MFC

Author

Commented:
I will implement your suggestion.  Thanks for your help.
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.