Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

Destroy Window problem

I am adding a CNiGraph object to a dialog box in Visual C++ 6.0 (using Measurement Studio). I then display the dialog as modeless. When I close the window and delete the pointer to the dialog box I get a exception error generated by the Graph (Can not access memory). I get around this by calling CGraph.DestroyWindow in OnClose for the dialog box. However this means that PostNCDestroy and OnDestroy will not be called for the derived class. Is this a problem for CNiGraph? Is this the proper way to handle this for tracking modeless dialog boxes?

Please some advice
0 Kudos
Message 1 of 8
(4,783 Views)
It's hard to tell what's happening in your project without seeing some code. I tried to reproduce this in a test project and didn't see the error. Basically what I did was I created a dialog resource (for this example, let's say the resource ID is IDD_MYDIALOG) and added a pointer member variable (for this example, let's say it's a CMyDialog* called m_pDialog) of the new dialog class to my main dialog class and I initialized it to NULL. In the code where I created the modeless dialog, I did this:

if (m_pDialog == NULL)
{
m_pDialog = new CMyDialog();
m_pDialog->Create(IDD_MYDIALOG, this);
m_pDialog->ShowWindow(SW_SHOW);
}

At the point where I wanted to close the window and delete the pointer, I did this:


if (m_pDialog != NULL)
{
m_pDialog->CloseWindow();
delete m_pDialog;
m_pDialog = NULL;
}

Please compare this to the code that was failing in your project and see what's different and reply with what you find. If you're still having problems, please post sample code that demonstrates how you're creating, showing, closing, and deleting the dialog. Thanks.

- Elton
Message 2 of 8
(4,783 Views)
Thank You for the reply. It is not just CNiGraph, but all NI user interface objects which are giving me a problem. I am Tracking the dialogs in the mainframe class of my application, it is an SDI with several views across which the modeless dialog needs to exist.
I create the modeless dialog in the main frame with
void CMainFrame::CreateScope()
{
if (NULL == pScope[0])
{
pScope[0] = new CDiaOScope(this);
pScope[0]->SetScopeNumber(0);
if (pScope[0]->Create(IDD_D_OScope,this))
pScope[0]->ShowWindow(SW_SHOW);
}
else if (NULL == pScope[1])
{
pScope[1] = new CDiaOScope(this);
pScope[1]->SetScopeNumber(1);
if (pScope[1]->Create(IDD_D_OScope,this))
pScope[1]->ShowWindow(SW_SHOW);
}
else if (NULL == pScope[2])
{
pScope[2] = new CDiaOScope(this);
pScope[2]->SetScopeNumber(2);
if (pScope[2]->Create(IDD_D_OScope,this))
pScope[2]->ShowWindow(SW_SHOW);
}
else if (NULL == pScope[3])
{
pScope[3] = new CDiaOScope(this);
pScope[3]->SetScopeNumber(3);
if (pScope[3]->Create(IDD_D_OScope,this))
pScope[3]->ShowWindow(SW_SHOW);
}
else if (NULL == pScope[4])
{
pScope[4] = new CDiaOScope(this);
pScope[4]->SetScopeNumber(4);
if (pScope[4]->Create(IDD_D_OScope,this))
pScope[4]->ShowWindow(SW_SHOW);
}

}
I create up to five scope dialogs as needed.

I am deleting the pointer with a call to a function in the main frame class from within the OnClose message handler of the scope dialog itself. Perhaps this is where I am running into trouble. The code is:

void CDiaOScope::OnClose()
{

CDialog::OnClose();
if (m_ScopeStarted.GetValue())
{
switch(ScopeNumber)
{
case 0:
KillTimer(TMR_OScope0);
break;
case 1:
KillTimer(TMR_OScope1);
break;
case 2:
KillTimer(TMR_OScope2);
break;
case 3:
KillTimer(TMR_OScope3);
break;
case 4:
KillTimer(TMR_OScope4);
break;
}
}


m_OScope.DestroyWindow();
m_XMax.DestroyWindow();
m_YMax.DestroyWindow();
m_XMin.DestroyWindow();
m_YMin.DestroyWindow();
m_ZoomX.DestroyWindow();
m_ZoomY.DestroyWindow();
m_ZoomXY.DestroyWindow();
m_PanY.DestroyWindow();
m_PanX.DestroyWindow();
m_PanXY.DestroyWindow();
m_AutoScaleY.DestroyWindow();
m_AutoScaleX.DestroyWindow();
m_AutoScaleXY.DestroyWindow();
m_Cursor.DestroyWindow();
m_CursorX.DestroyWindow();
m_CursorY.DestroyWindow();
m_ScopeStarted.DestroyWindow();

CMainFrame* pFrame = DYNAMIC_DOWNCAST(CMainFrame,
GetParentFrame());
pFrame->CleanUpScope(ScopeNumber);

}
The function which deletes the pointer is at the end.

void CMainFrame::CleanUpScope(int Number)
{

delete pScope[Number];
pScope[Number] = NULL;

}

That seems simple enough.
The error I get without the DestroyWindow calls is
an access violation. When I remove the destroy window call for a CNiButton I get the error at the top line below in the call stack.

68677561()
SERVOCONTROL! NI::CNiControl::WndProc(struct HWND__ *,unsigned int,unsigned int,long) + 105 bytes
USER32! 77e11d0a()
USER32! 77e12bcc()
USER32! 77e12b84()
NTDLL! 77fa02ff()
COleDispatchImpl::Release(COleDispatchImpl * const 0x0272e058) line 1117
COleDispatchDriver::ReleaseDispatch() line 155
COleDispatchDriver::~COleDispatchDriver() line 85 + 15 bytes
COleControlSite::~COleControlSite() line 112 + 33 bytes
COleControlSite::`scalar deleting destructor'(unsigned int 1) + 15 bytes
COleControlSite::DestroyControl() line 291 + 31 bytes
CWnd::DestroyWindow() line 971 + 17 bytes
CWnd::~CWnd() line 760
SERVOCONTROL! NI::CNiControl::~CNiControl(void) + 31 bytes
SERVOCONTROL! NI::CNiButton::~CNiButton(void) + 74 bytes
CDiaOScope::~CDiaOScope() + 449 bytes

How are you closing the modeless dialog in your example? My goal was to use the close button on the frame of the dialog to close it and the above method seemed like the way to do it.

Thanks for any help

Matthew
0 Kudos
Message 3 of 8
(4,783 Views)
In my example I was closing the modeless dialog programmatically in a message handler in the parent dialog. Looking at the code that you posted, I think that the problem is with deleting the pointer in the OnClose method. Try overriding PostNcDestroy and deleting the pointer there instead. Also, override OnOK and OnCancel and call DestroyWindow at the end of those methods for the modeless dialog. Do not call the base class CDialog::OnOK and CDialog::OnCancel in these methods because they call CDialog::EndDialog, which should only be called for modal dialogs. Give this a shot and see how it works.

- Elton
0 Kudos
Message 4 of 8
(4,783 Views)
Thanks, That did the trick. It just makes sense that I would call these in PostNcDestroy.
matthew
0 Kudos
Message 5 of 8
(4,783 Views)
It turns out putting the call to PostNcDestroy did not work. This was not called until I actually exited the application. Instead I removed the call to the default OnClose in its message handler and put a call to destroyWindow in my clean-up function

Changes:void CDiaOScope::OnClose()
{
CMainFrame* pFrame = DYNAMIC_DOWNCAST(CMainFrame, GetParentFrame());
if (m_ScopeStarted.GetValue())
{
switch(ScopeNumber)
{
case 0:
KillTimer(TMR_OScope0);
break;
case 1:
KillTimer(TMR_OScope1);
break;
case 2:
KillTimer(TMR_OScope2);
break;
case 3:
KillTimer(TMR_OScope3);
break;
case 4:
KillTimer(TMR_OScope4);
break;
}
pFrame->DecreaseAccessNumber(ScopeNumber);
}

p
Frame->CleanUpScope(ScopeNumber);

}

and to clean up

void CMainFrame::CleanUpScope(int Number)
{

if (NULL != pScope[Number])
{
pScope[Number]->DestroyWindow();
delete pScope[Number];
pScope[Number] = NULL;
}

}

What do you think?
matthew
0 Kudos
Message 6 of 8
(4,783 Views)
In which class were you overriding PostNcDestroy? The main application window class or the modeless dialog class? If it's the former, it would make sense that PostNcDestroy is not called until the application is exited, but if it's the latter, it should be called much sooner than that (assuming that you're closing them before closing the application). Just to clarify, I was suggesting overriding PostNcDestroy in the modeless dialog class and it would contain a "delete this;" call in it to delete the dynamically allocated modeless dialog class.

- Elton
0 Kudos
Message 7 of 8
(4,783 Views)
I was overiding it in the modeless dialog class. It is a bit strange to me as well that it is not being called. I was still overiding OnClose to kill the timer, maybe that caused it not to be called. I do not think it would matter.

The way I am doing it now seems okay. The default implementation of OnClose just calls DestroyWindow, so I just do it for it.
matthew
0 Kudos
Message 8 of 8
(4,783 Views)