I've derived a class from CDialog called CRRDialog, which contains a few
vars and functions I want to be able to use in all the Dialogs in my app. I
then derive most (but not all) of my Dialogs from CRRDialog instead of
CDialog. The main AppDlg is still derived from CDialog.
I've found that clean up routines I place in these CRRDialog-derived classes
are not called when the App is shut down. The debugger gives me a warning:
Warning: calling DestroyWindow in CDialog::~CDialog --
OnDestroy or PostNcDestroy in derived class will not be called.
And sure enough I have Memory leaks where clean up routines I've put in my
CRRDialog-derived classes are not called. I've tried using the Class Wizard
to put these clean up routines in WM_CLOSE, WM_DESTROY and PostNcDestroy,
but none of these functions seem to be called.
It was a bit tricky getting that CRRDialog into the Heirarchy considering I
don't actually create any instances/windows from it, just use it to derive
from. Is this a Bad Thing? How can I get my clean up routines called?
Any suggestions?
Thanks!
=== _ \=== _ \=== ___/= |== /========== <br...@nospam.interlog.com> ===
=== /= /== /= /== /==== |= /=========================================
=== __ <== __ <== __/== /= | /==================== = <ICQ #2059215> ===
=== /== /= /== /= /==== /== /========== the wandering.net.wanderer ===
===_____/=_/==_/=____/=_/===_/======= http://www.interlog.com/~bren ===
-> When replying, please remove "nospam" from my address <-
{
...
CDialog dlg(IDD_SOMTHING);
dlg.DoModal();
}
DoModal "creates" the dialog and "destroys" it before returning.
Sample 2:
{
m_pDlg = new CDialog; // m_pDlg of type CDialog*
m_pDlg->Create(IDD_SOMTHING);
}
and somewhere in the cleanup you call:
delete m_pDlg;
The last delete does not cleanly destroy the dialog.
Your shoul call m_pDlg->DestroyWindow before the
delete.
The problem is a basic C++ issue. Consider the
following:
class A
{
public:
A() {}
virtual ~A() { Cleanup(); }
virtual void Cleanup() {}
};
class B : public A
{
B() {}
virtual ~B() {}
virtual void Cleanup() {}
};
When the destructor A::~A() is running, the instance does
no longer know, that it was once an instance of class B
because this information was removed by the B::~B() destructor
which ran before A::~A(). As a result the call to Cleanup() in A::~A()
will call A::Cleanup() and never B::Cleanup despite the virtuality of
the method.
The same is true for the cleanup of CWnd derived classes. You
can override OnDestroy and PostNcDestroy to do additional
cleanup before or after the HWND member becomes invalid.
These methods are called during the CWnd::DestroyWindow call.
In the destructor of CWnd theres a check whether the m_hWnd member
is still there and the ASSERT warns you, that you forgot to call
DestroyWindow.
Regards, Roger