Page 1 of 1

Accesare m_wndSplitter

Posted: 18 May 2011, 15:33
by mesajflaviu
Intr-o aplicatie MDI , in child frame creez mai multe ferestre de tip CSplitterWnd :

Code: Select all

BOOL CDataChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	// TODO: Add your specialized code here and/or call the base class

	if(! m_wndSplitter.CreateStatic(this, 1, 2))return FALSE;

	if(! m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CDataExplorerTree), CSize(nWidth, 0), pContext))
	{
		m_wndSplitter.DestroyWindow();
		return FALSE;
	}

	if(! m_wndSplitter2.CreateStatic(&m_wndSplitter,3,1,WS_CHILD | WS_VISIBLE | WS_BORDER,m_wndSplitter.IdFromRowCol(0,1)))
	{
		m_wndSplitter2.DestroyWindow();
		return FALSE;
	}

	if(! m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(CMy1View),CSize(0,300),pContext))
	{
		m_wndSplitter2.DestroyWindow();
		return FALSE;
	}

	if(! m_wndSplitter2.CreateView(1,0,RUNTIME_CLASS(CMy2View),CSize(0,200),pContext))
	{
		m_wndSplitter2.DestroyWindow();
		return FALSE;
	}

	if(! m_wndSplitter2.CreateView(2,0,RUNTIME_CLASS(CMy3View),CSize(0,200),pContext))
	{
		m_wndSplitter2.DestroyWindow();
		return FALSE;
	}

	return TRUE;
}
dar cand vreau sa accesez m_wndSplitter2 din CMDIChildWnd :

Code: Select all

void CDataChildFrame::SomeFunction()
{
	CMy2View* pView = (CMy2View*)m_wndSplitter2.GetPane(1,0);
}
dar am eroare :

Code: Select all

ASSERT_VALID fails with illegal vtable pointer.
intrebarea mea este , cum accesez corect panourile din ChildFrame ?
Multumesc.

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 09:15
by Ovidiu Cucu
La prima vedere nu pare nimic gresit in codul pe care l-ai pus aici.
Mai mult l-am pus intr-o aplicatie de-a mea si a mers fara probleme.

Te joci cumva cu DLL-uri?
Cusomizezi cumva ferestrele splitter (ai derivat din CSplitterWnd)?
Poate cumva chemi GetPane de unde nu trebuie...
Prima data incearca un "Rebuild All" la toate modulasele din project.

Nu stiu. Daca as avea o aplicatie demo care reproduce bug-ul poate ca mi-as da rapid seama.

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 09:22
by mesajflaviu
Ciudat ... nu folosesc nici un DLL custom ... mai incerc niste lucruri pe aici sa vad ce iese . Proiectul e cam mare , nu-l pot pune aici , dar daca nu reusesc nici cum fac un demo mic si-l atasez dar numai dupa ce epuizez toate solutiile. Multumesc.

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 10:20
by mesajflaviu
Am reusit sa reproduc gogomania intr-o aplicatie test ... nu stiu ce nu fac bine .

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 11:23
by mesajflaviu
In CChildFrame am :

Code: Select all

void CChildFrame::SomeFunction()
{
	CWnd* pTrace = (CWnd*)m_wndSplitter2.GetPane(1,0);
	if(pTrace)pTrace->ShowWindow(SW_HIDE);
}
iar la click pe CTreeView :

Code: Select all

void CLeftView::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	CChildFrame* pChild = (CChildFrame*)GetParent();
	if(pChild)pChild->SomeFunction();

	*pResult = 0;
}
dar cand ating CTreeView crapa si ma duce la :

Code: Select all

CWnd* CSplitterWnd::GetPane(int row, int col) const
{
	ASSERT_VALID(this); // <-- aici !!!

	CWnd* pView = GetDlgItem(IdFromRowCol(row, col));
	ASSERT(pView != NULL);  // panes can be a CWnd, but are usually CViews
	return pView;
}

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 11:32
by Viorel
Dacă în loc de

Code: Select all

CChildFrame * pChild = (CChildFrame*)GetParent();
ai fi scris

Code: Select all

CChildFrame * pChild = STATIC_DOWNCAST(CChildFrame, GetParent());
atunci ai fi observat care e problema: valoarea returnată de GetParent nu este CChildFrame. Ar trebui să încerci alte moduri pentru accesarea lui CChildFrame. De exemplu:

Code: Select all

CChildFrame * pChild = STATIC_DOWNCAST(CChildFrame, GetParent()->GetParent());

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 14:22
by mesajflaviu
Intradevar , daca obtin pointer in modul urmator :

Code: Select all

void CLeftView::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	CChildFrame* pChild = (CChildFrame*)GetParent()->GetParent();
	if(pChild)pChild->SomeFunction();

	*pResult = 0;
}
atunci e valid ... mai am o nedumerire . La acel click pe tree view , as vrea sa ascund cu totul randul 1 ( si 2 eventual ) din m_wndSplitter2 ( din coloana 2 ) . Am incercat in mai multe feluri :

Code: Select all

void CChildFrame::SomeFunction()
{
	CSplitterWnd* pTrace = (CSplitterWnd*)m_wndSplitter2.GetPane(1,0);
	if(pTrace)pTrace->ShowWindow(SW_HIDE);

	m_wndSplitter2.RecalcLayout();
}
in acest fel nu se redeseneaza fereastra ascunsa ( desi am invalidat-o ).
Apoi m-am gandit sa reduc dimensiunea panourilor la 0 :

Code: Select all

void CChildFrame::SomeFunction()
{
	CRect rect;
	m_wndSplitter2.GetWindowRect(rect);
	m_wndSplitter2.SetRowInfo(0,rect.Height(),rect.Height() / 10);
	m_wndSplitter2.SetRowInfo(1,0,0);
//	m_wndSplitter2.SetRowInfo(2,0,0);

	m_wndSplitter2.RecalcLayout();
}
si functioneaza dar nu este practica fiindca la un restore a ferestrei panoul cu dimensiune 0 redevine vizibil ... exista vreo metoda de a ascunde total vreun panou ca mai apoi sa fie adus inapoi ?

Re: Accesare m_wndSplitter

Posted: 19 May 2011, 16:55
by Ovidiu Cucu
Completand ce-a spus deja Viorel, daca vrei sa obtii frame-ul unui view dat, poti face asta direct si fara sa-ti mai bati capul, apeland GetParentFrame.

Daca vrei sa ascunzi/arati in mod dinamic paneluri intr-un splitter static, n-ai incotro, trebuie sa derivezi propria ta clasa din CSplitterWnd.
Vezi clasa CCustomSplitter din proiectul LogExpert.