Accesare m_wndSplitter

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Accesare m_wndSplitter

Post by mesajflaviu » 18 May 2011, 15:33

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.



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Accesare m_wndSplitter

Post by Ovidiu Cucu » 19 May 2011, 09:15

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.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Accesare m_wndSplitter

Post by mesajflaviu » 19 May 2011, 09:22

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.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Accesare m_wndSplitter

Post by mesajflaviu » 19 May 2011, 10:20

Am reusit sa reproduc gogomania intr-o aplicatie test ... nu stiu ce nu fac bine .
Attachments
Test.zip
(92.2 KiB) Downloaded 260 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Accesare m_wndSplitter

Post by mesajflaviu » 19 May 2011, 11:23

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;
}

Viorel
Microsoft MVP
Microsoft MVP
Posts: 293
Joined: 13 Jul 2007, 12:26

Re: Accesare m_wndSplitter

Post by Viorel » 19 May 2011, 11:32

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());

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Accesare m_wndSplitter

Post by mesajflaviu » 19 May 2011, 14:22

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 ?

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Accesare m_wndSplitter

Post by Ovidiu Cucu » 19 May 2011, 16:55

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.

Post Reply