My user will need to be able to open any number of graphing
windows(CDockablePane) in my application. When the window is closed, I want
the pane to be destroyed.
In order to do this I will have my window catch the press close button event
(CPane::OnPressCloseButton) and then have it call DestroyWindow().
reading DestroyWindow description, it looks like it does everything but it
does not destroy the CWnd object.
So how do I destroy the CWnd object? Do i just simply need to call delete
(pointer to graph window). I was thinking I could override the NotifyParent
function to catch child destroyed event and then deleting it then, however
the parent gets notified BEFORE any destruction takes place.
I'm not sure if this is possible, but after calling DestroyWindow() within
the OnPressCloseButton() function, could I just call "delete this" to free
up any memory used by the graph window?
Any suggestions are greatly appreciated.
Nick
You cannot delete an object earlier than the PostNcDestroy handler.
joe
On Fri, 2 May 2008 10:59:01 -0700, Nick Schultz <NickS...@discussions.microsoft.com>
wrote:
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
When I create the window, it starts out docked to the main frame. If I
undock the window and then close it, those functions do not get called. If I
leave it docked, or undock it and dock it again and then close the window,
those functions get called.
After going through those two functions, I then get an Access violation:
Unhandled exception at 0x78a75e55 (mfc90ud.dll) in CanAnalyzer.exe:
0xC0000005: Access violation reading location 0xfeef000e.
and the break point is at the return statement:
LRESULT CWnd::Default()
{
// call DefWindowProc with the last message
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
return DefWindowProc(pThreadState->m_lastSentMsg.message,
pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
}
Here is the code of the closing functions:
void CGrapher::OnPressCloseButton()
{
DestroyWindow();
}
void CGrapher::PostNcDestroy(){
delete this;
}
So i guess I got a couple questions now, why am i getting that access
violation and why wont those functions get called when the CDockablePane is
undocked(floating)?
Thanks for the help,
Nick
void CMainFrame::OnRmtSend2Btn()
{
CGrapher* newWnd;
newWnd = new CGrapher();
if(!newWnd->Create(_T("Graph Window"), this, CRect(0, 0, 300, 300), TRUE
,m_windowCounter++, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
| CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create BITWnd window\n");
return; // failed to create
}
newWnd->EnableDocking(CBRS_ALIGN_ANY);
DockPane(newWnd);
return;
Dont call DestroyWindow; use PostMessage(WM_CLOSE) instead. See if
that helps.
--
Ajay
Also, I have not installed the feature pack so I cant confirm but does
CDockablePane override PostNcDestroy? If it does, what is it doing in
it? Also, you should call the base class in PostNcDestroy before
calling delete this.
You should also read this: http://msdn.microsoft.com/en-us/library/5zba4hah(VS.80).aspx
---
Ajay
Thanks Ajay, it looks like I'm getting closer, however these functions don't
get called at all when the CDockablePane is not docked. I am confirming this
by setting breakpoints and watching the thread list in Process Explorer.
1. When a CDockablePanel is docked and I hit the 'X' button, the window
disapears and memory and thread is cleared,which is the desired action,
however it looks like there is a base control still there, since the
ListCtrl in the mainframe will not resize to take up the whole frame. This
disapears when I resize, move, or create a new panel.
2. If the panel is in autohide mode and i close it, the panel disapears,
HOWEVER the tab bar stays with the tab for the panel, if I try to resize or
move , I get an access violation. I also get an access violation if I
hover the mouse over the tab.
3. If the panel is floating and I hit the 'X' button, the panel goes away,
however my OnPressCloseButton function does not get called, thus does not
free resources
4. When the panel is floating, I right click on the window and I get a menu
of ( Docking,X Floating,or Hide). If i select Hide, the OnPressCloseButton
function gets called and resources are freed
5. If the panel is floating, and I create another panel and dock it with
the floating panel, I can then hit the 'X' on one of the docked panels and
it will free resources AND removes the panel from the screen. This is the
desired result, however I want to be able to push the "X". (So it looks like
it has to be docked for the OnPressCloseButton to be called, when it floats
it uses a miniframe, so should is there a message that the miniframe would
post when it's "X" is pushed?)
6. If the panel is docked and I right click and select Hide, resources are
freed, however the panel stays and I get the same results as in [1]&[2].
Thanks you guys for the help,
Nick
"Nick Schultz" <NickS...@discussions.microsoft.com> wrote in message
news:8824E7C6-FA47-487A...@microsoft.com...
>It still doesn't look like I am destroying the CDockable Panel correctly. I
>am getting some very wierd responses. I'll try to list all of the
>occurances I'm noticing, perhaps somebody will see something:
>
>1. When a CDockablePanel is docked and I hit the 'X' button, the window
>disapears and memory and thread is cleared,which is the desired action,
>however it looks like there is a base control still there, since the
>ListCtrl in the mainframe will not resize to take up the whole frame. This
>disapears when I resize, move, or create a new panel.
****
Yes, that is correct behavior. You will need to call RecalcLayout (if I am remembering
the name correctly). If you don't force the recalculation of the layout explicitly, it
won't happen.
****
>
>2. If the panel is in autohide mode and i close it, the panel disapears,
>HOWEVER the tab bar stays with the tab for the panel, if I try to resize or
>move , I get an access violation. I also get an access violation if I
>hover the mouse over the tab.
****
I've not tried this, so I don't have a clue here...I suspect the issue is related to the
fact that the tab has not been told to go away, because your destruction happens at a
level below the window that is managing the tab. You will probably need to PostMessage to
the parent a notification that the window is being destroyed, so you can force the tab to
go away. Beyond that, I can't say
****
>
>3. If the panel is floating and I hit the 'X' button, the panel goes away,
>however my OnPressCloseButton function does not get called, thus does not
>free resources
****
It would be worthwhile studying what sequence of messages is sent, using Spy++. The
OnPressClose button should not free ANY resources at all; any resources that must be freed
should be freed in the OnDestroy handler. That will help.
****
>
>4. When the panel is floating, I right click on the window and I get a menu
>of ( Docking,X Floating,or Hide). If i select Hide, the OnPressCloseButton
>function gets called and resources are freed
****
This sounds odd. I'd be suspicious of what triggers on OnPressCloseButton message
****
>
>5. If the panel is floating, and I create another panel and dock it with
>the floating panel, I can then hit the 'X' on one of the docked panels and
>it will free resources AND removes the panel from the screen. This is the
>desired result, however I want to be able to push the "X". (So it looks like
>it has to be docked for the OnPressCloseButton to be called, when it floats
>it uses a miniframe, so should is there a message that the miniframe would
>post when it's "X" is pushed?)
****
I suspect that what is happening is that you have a view inside the frame, so putting
handlers for messages in the view will *not* handle any messages sent to the containing
frame. This is why you want to put your resource-freeing logic in the OnDestroy handler,
because that makes it independent of who is doing the destruction.
****
>
>6. If the panel is docked and I right click and select Hide, resources are
>freed, however the panel stays and I get the same results as in [1]&[2].
****
The RecalcLayout method should fix this. Note that it must be called in the containing
frame window, not in the view itself.
That's all I can think of at the moment; I have virtually no experience with docking
windows.
joe
****
email: newc...@flounder.com