15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Memory leak problem with Splitter window

Davoud Maha -- davoud@jupiter.Legato.COM
Friday, May 10, 1996


        VC++ 4.1, NT 3.51

        I am trying to create a splitter window with 1 column and 2 rows.
All the 
examples and docs I have seen uses CMDChildWnd or CFrameWnd as the parent of
the splitter window.

        My problem is that the parent of my Splitter windows needs to be a
CWnd. Since that 
is the case, I don't get the OnCreateClient message so that I can setup my
static splitter and
create the views inside of it.

        I have overridden the Create function for the splitter, and I am
doing the static 
create and view creates there. Everything seems to work, but when I exit the
debugger, I get
some memory leakes. The memory leaks point to the two RUTIMES_CLASSes that I
have in create.

        I know this is NOT the right model, so please help if you know the
answer.
Also the code calling this create does not have a valid pContext since the
caller
is a CWnd object.
       

BOOL CMonitorSplitterWnd::Create(LPCTSTR /* lpszClassName */,
                         LPCTSTR /* lpszWindowName */,
                         DWORD /* dwStyle */,
                         const RECT& /* rect */,
                         CWnd* pParentWnd,
                         UINT /* nID */,
                         CCreateContext* pContext) // <- Not really valid 
{
                if (!CreateStatic(pParentWnd, 2, 1, WS_CHILD
,AFX_IDW_PANE_FIRST ))
		{
			TRACE0("Failed to CreateStaticSplitter\n");
			return ( FALSE );
		}

	   	// add the first splitter pane - the default view in column 0
		if (!CreateView(0, 0, 
		  RUNTIME_CLASS( CMonitorGraph) , CSize(100, 400), pContext))
		{
			TRACE0("Failed to create first pane\n");
			return ( FALSE );
		}
		// add the second splitter pane
	   	if (!CreateView(1, 0,
			RUNTIME_CLASS(CMonitorMsg), CSize(100, 20), pContext))
		{
			TRACE0("Failed to create second pane\n");
			return ( FALSE );
		}
		
		return TRUE;	  
}



        Thanks, Davoud.




Frederic Steppe -- FredericS@msn.com
Monday, May 13, 1996

>        VC++ 4.1, NT 3.51
>
>        I am trying to create a splitter window with 1 column and 2 rows.
>All the 
>examples and docs I have seen uses CMDChildWnd or CFrameWnd as the parent of
>the splitter window.
>        My problem is that the parent of my Splitter windows needs to be a
>CWnd. Since that 
>is the case, I don't get the OnCreateClient message so that I can setup my
>static splitter and
>create the views inside of it.
>        I have overridden the Create function for the splitter, and I am
>doing the static 
>create and view creates there. Everything seems to work, but when I exit the
>debugger, I get
>some memory leakes. The memory leaks point to the two RUTIMES_CLASSes that I
>have in create.
>        I know this is NOT the right model, so please help if you know the
>answer.
>Also the code calling this create does not have a valid pContext since the
>caller
>is a CWnd object.


The memory leaks comes from the fact that a CWnd doesn't handle the views 
mechanism.  You have to make the parent window a kind of CFrameWnd, or to 
handle everything by yourself.  The pContext problem is the same.  You'll have 
to do the job and create one.

By the way, why can't you parent window be a CFrameWnd ?

Frederic Steppe (frederics@msn.com)



Frederic Steppe -- FredericS@msn.com
Thursday, May 16, 1996

>        VC++ 4.1, NT 3.51
>
>        I am trying to create a splitter window with 1 column and 2 rows.
>All the 
>examples and docs I have seen uses CMDChildWnd or CFrameWnd as the parent of
>the splitter window.
>        My problem is that the parent of my Splitter windows needs to be a
>CWnd. Since that 
>is the case, I don't get the OnCreateClient message so that I can setup my
>static splitter and
>create the views inside of it.
>        I have overridden the Create function for the splitter, and I am
>doing the static 
>create and view creates there. Everything seems to work, but when I exit the
>debugger, I get
>some memory leakes. The memory leaks point to the two RUTIMES_CLASSes that I
>have in create.
>        I know this is NOT the right model, so please help if you know the
>answer.
>Also the code calling this create does not have a valid pContext since the
>caller
>is a CWnd object.

I think a little example is better than a long speach. Here is my way to 
handle multiple views, including splitters, in an MDI child frame :

1. Define a class for your splitter window (even if you don't have anything 
special to do, you need this for dynamic creation)

class CMySplitter : public CSplitterWnd
{
	DECLARE_DYNCREATE(CMySplitter);
protected:
	CMySplitter();

public:
	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD 
dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* 
pContext = NULL);

};

IMPLEMENT_DYNCREATE(CMySplitter, CSplitterWnd);

CMySplitter::CMySplitter()
{
	// Initialize here ...
}

BOOL CMySplitter::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD 
dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* 
pContext)
{
	CreateStatic(pParentWnd, 2, 2, dwStyle, nID);

	SIZE IdealSize;
	IdealSize.cx = 100;
	IdealSize.cy = 100;

	// In this sample, create 4 static panes

	CreateView(0, 0, RUNTIME_CLASS(CMdiViewsView), IdealSize, pContext);
	CreateView(0, 1, RUNTIME_CLASS(CMdiViewsView), IdealSize, pContext);
	CreateView(1, 0, RUNTIME_CLASS(CMdiViewsView), IdealSize, pContext);
	CreateView(1, 1, RUNTIME_CLASS(CMdiViewsView), IdealSize, pContext);

	return TRUE;
}


2. Override CChildFrame::OnCreateClient to create all your views (and add 
members to store them)

// Members of CChildFrame :

	CWnd *m_pWnd[3];
	UINT m_nActiveWnd;


BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* 
pContext) 
{
	pContext->m_pNewViewClass = RUNTIME_CLASS(CMdiViewsView);
	m_pWnd[0] = CreateView(pContext, AFX_IDW_PANE_FIRST);

	pContext->m_pNewViewClass = RUNTIME_CLASS(CMySplitter);
	m_pWnd[1] = CreateView(pContext, AFX_IDW_PANE_FIRST + 1);

	pContext->m_pNewViewClass = RUNTIME_CLASS(CMdiViewsView);
	m_pWnd[2] = CreateView(pContext, AFX_IDW_PANE_FIRST + 2);

	m_nActiveWnd = 0;
	
	return TRUE;	// Yes, I know, some checking has to be done.  I'm optimistic by 
nature.
}

You can create more views, and view of different classes, of course.  You can 
even define different splitter classes and add them too.  The view with ID 
equal to AFX_IDW_PANE_FIRST will be the initial view.  Always set m_nActiveWnd 
to the correct item (the first one here, but you may switch them).


3. Override CChildFrame::DestroyWindow() to delete the splitter

BOOL CChildFrame::DestroyWindow() 
{
	m_pWnd[1]->DestroyWindow();		// Must destroy and delete the splitter(s)
	delete m_pWnd[1];

	return CMDIChildWnd::DestroyWindow();	// Better succeed, as the splitter 
isn't here anymore !
}


4. Add a method to switch the views (member of the child frame)

void CChildFrame::ChangeView(UINT nView)
{
	if(nView == m_nActiveWnd) return;

	m_pWnd[m_nActiveWnd]->SetDlgCtrlID(m_pWnd[nView]->GetDlgCtrlID());
	m_pWnd[nView]->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

	m_pWnd[nView]->ShowWindow(SW_SHOW);
	m_pWnd[m_nActiveWnd]->ShowWindow(SW_HIDE);

	RecalcLayout();	

	m_nActiveWnd = nView;
}


5. Remove the default view class from the document template (in InitInstance)

	pDocTemplate = new CMultiDocTemplate(
		IDR_MDIVIETYPE,
		RUNTIME_CLASS(CMdiViewsDoc),
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
		NULL);	// No default view, please.


6. Try it !

What you have to do is to call ChangeView with the number of the view that 
must be displayed (from 0 to 2 here).
I did it from menu items, for test purposes, but you can do it another way 
(tab controls, etc).

void CChildFrame::OnView1() 
{
	ChangeView(0);
}

void CChildFrame::OnView2() 
{
	ChangeView(1);
}

void CChildFrame::OnView3() 
{
	ChangeView(2);
}


Good luck.


Frederic Steppe (frederics@msn.com)




| Вернуться в корень Архива |