Page 2 of 3

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 19 Dec 2010, 00:27
by mesajflaviu
Va asptept ! :welcome:

P.S. Sper sa nu ma intelegeti gresit , recunostinta mea nu se reduce la bere !!!

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 12 May 2011, 21:16
by mesajflaviu
Am mai dat clasa CListCtrlEx prin faina si ou si am adus-o in stadiul de a putea-o folosi in orice stil ( LVS_SMALLICON , LVS_ICON , LVS_LIST , LVS_REPORT ) pusa deasupra unui view ... bun , dar la ideea lui Ovidiu de aici , am incercat sa folosesc aceasta clasa , CListCtrlEx , ca si control la un CListView standard , asa cum propune articolul din codeguru.

Si aproape am reusit , mai ramane de rezolvat accesul la header , si ar iesi un lucru bun daca as trece si peste acest pas ... revin cu un post in care sa spun ce am facut pana acum , si care e problema ...

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 12 May 2011, 21:36
by mesajflaviu
Asa cum spune articolul , am derivat din CListCtrlEx o noua clasa , CChildListCtrlEx :

Code: Select all

class CChildListCtrlEx : public CListCtrlEx
{
// Construction
public:
	CChildListCtrlEx();

// Attributes
public:
	friend class CTestList6View;

// Operations
public:

#ifdef _DEBUG
	void AssertValid() const {}
#endif
...
...
	DECLARE_MESSAGE_MAP()
};
iar clasa mea view , derivata din CListView , are

Code: Select all

protected:
	CChildListCtrlEx m_List;
iar unde as folosi GetListCtrl() in view , folosesc m_List .
In view mai trebuie setate niste variabile membru ale listcontrolului :

Code: Select all

int CTestList6View::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if(CListView::OnCreate(lpCreateStruct) == -1)return -1;

	// TODO: Add your specialized creation code here

	m_List.m_hWnd = m_hWnd;
	m_List.m_pfnSuper = m_pfnSuper;
	m_List.PreSubclassWindow();

	return 0;
}
unde se face si subclasarea listcontrolului , apoi se suprascriu 3 handlere : PreTranslateMessage, OnChildNotify si WindowProc , dupa care totul functioneaza aparent normal ...

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 12 May 2011, 22:07
by mesajflaviu
Problema apare cand se incearca accesul header-ul CHeaderCtrlEx , compilatorul zice ca se acceseaza un obiect necreat ( si am incredere in el ) , o sa atasasez la sfarsit si un proiect demo pentru exemplificare :( ... Cand incerc sa folosesc metode CHeaderCtrl nu am probleme , dar cand incerc sa accesez metode din CHeaderCtrlEx crapa totul ( in modul Debug se poate vedea clar totul ) , semn ca CHeaderCtrlEx nu e creat .

CListCtrlEx creaza header-ul in WindowProc(...) :

Code: Select all

LRESULT CListCtrlEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case LVM_INSERTCOLUMN:
		{
			TRACE("Here I create column\n");
			if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)break;
			LRESULT ret = CListCtrl::WindowProc(message, wParam, lParam);
			if((int)ret >= 0)
			{
				LVCOLUMN* pCol = (LVCOLUMN*)lParam;
				CHeaderCtrlEx::CItemData* pData = new CHeaderCtrlEx::CItemData(pCol->cx, TRUE, TRUE);
				m_HeaderCtrl.SetItemData((int)ret, (DWORD_PTR)pData);
			}
			return ret;
		}
	case LVM_DELETECOLUMN:
		{
			if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)break;
			CHeaderCtrlEx::CItemData* pData = (CHeaderCtrlEx::CItemData*)m_HeaderCtrl.GetItemData((int)wParam);
			ASSERT(pData);
			LRESULT ret = CListCtrl::WindowProc(message, wParam, lParam);
			if((BOOL)ret && pData)delete pData;
			return ret;
		}
	}

	return CListCtrl::WindowProc(message, wParam, lParam);
}
insa cum era de asteptat , aplicatia nu trece pe aici ( TRACE("Here I create column\n"); ) ... dar nu inteleg de ce !?

Am incercat "variatiuni pe diferite teme" in CTestList6View::WindowProc(...) :

Code: Select all

LRESULT CTestList6View::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class

	LRESULT lResult = 0;
	if(! CListView::OnWndMsg(message, wParam, lParam, &lResult))
	{
		if(! m_List.OnWndMsg(message, wParam, lParam, &lResult))
		{
			lResult = DefWindowProc(message, wParam, lParam);
//			lResult = m_List.WindowProc(message, wParam, lParam);
		}
	}

	return lResult;
}
insa fara succes , dar cred ca aici e problema ... se pare ca CTestList6View nu ruteaza WindowProc prin CListCtrlEx::WindowProc(...)

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 12 May 2011, 22:39
by mesajflaviu
Atasez si proiectul demo , poate cand aveti timp va uitati peste el ...

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 12 May 2011, 23:14
by Ovidiu Cucu
La o prima vedere.
Intr-o aplicatie MFC, una din ultimile functii virtuale pe care le-as suprascrie ar fi CWnd::WindowProc.
Era intradevar nevoie?

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 13 May 2011, 07:57
by mesajflaviu
Am testat aplicatia si fara CTestList6View::WindowProc(...) , dar la fel , aplicatia nu trece prin CListCtrlEx::WindowProc(...).

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 13 May 2011, 08:10
by mesajflaviu
Sau sa inteleg ca ar trebui sa renunt la CListCtrlEx::WindowProc(...) ? ( De fapt la mesajul LVM_INSERTCOLUMN , LVM_DELETECOLUMN din CListCtrlEx::WindowProc , dar nu stiu daca ar fi o solutie buna fiindca atunci n-as mai avea editorul activ - mesajul UM_HIDEEDITOR)

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 13 May 2011, 12:04
by Ovidiu Cucu
Bine acum nu inteleg de ca ai derivat inca odata din CListCtrlEx fara sa adaugi nimic dar, in fine. Sa zicem ca adaugam acuma. :)

Eu unul nu suprascriu CWnd::WindowProc pentru ca ar fi ca si cum as arunca MFC-ul si m-as apuca de raw-WinAPI.
In MFC exista metode care in fond si la urma urmei nu fac decat sa trmita mesaje, macro-uri care mapeaza mesaje sau notificari (cu care ma ajuta wizard-ul), tocmai ca sa ne faca viata mai usoara.
Altfel in WindowProc ar trebui sa ma uit cu atentie in documentatia mesajelor sa vad ce contin, cum le tratez, ce si pe unde intorc.
Nu-i nevoie nici pentru mesaje custom, cum ar fi la tine acel UM_HIDEEDITOR pe care pot frumos si elegand sa-l mapez cu ON_MESSAGE.

Vreau sa mai adaug ceva la ce fac by default metodele din MFC?
No problem, le scriu pe ale mele in clasa derivata.
Exemple:

Code: Select all

int CChildListCtrlEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, 
                                   int nFormat /*= LVCFMT_LEFT*/, 
                                   int nWidth /*= -1*/, int nSubItem /*= -1*/)
{
   // call base class method for default processing
   int nRet = CListCtrl::InsertColumn(nCol, lpszColumnHeading, 
                                      nFormat, nWidth, nSubItem);

   // do what my muscles want
	CHeaderCtrlEx::CItemData* pData = new CHeaderCtrlEx::CItemData(nWidth, TRUE, TRUE);
	m_HeaderCtrl.SetItemData(nRet, (DWORD_PTR)pData);

   return nRet;
}

Code: Select all

BOOL CChildListCtrlEx::DeleteColumn(int nCol)
{
   // do what my muscles want
   CHeaderCtrlEx::CItemData* pData = 
      (CHeaderCtrlEx::CItemData* )m_HeaderCtrl.GetItemData(nCol);
   delete pData;

   // call base class method for default processing
   return CListCtrl::DeleteColumn(nCol);
}
O mica observatie colaterala:
Aici n-am gasit probleme cu memory leaks.
Totusi, daca lucrezi cu MFC, e bine ca in orice fisier .cpp sa pui la inceput:

Code: Select all

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
Asta iti permite sa detectezi usor sursa la memory leaks.
Probabil, domnul Chen Hao nu stia asta sau i-a fost lene s-o puna in HeaderCtrlEx.cpp. :)

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 13 May 2011, 12:19
by mesajflaviu
Ideea era sa fac totul in CListCtrlEx si nu in CChildListCtrlEx pentru a putea folosi listcontrolul si in CListView si ca (virgula) control standard ( intr-un form view de exemplu ) , dar aici cred ca totuna ... Buna idee , ma apuc de lucru , sa vad ce iese ...

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 14 May 2011, 09:36
by mesajflaviu
Pana la urma am reusit ... multumesc mult !!! ... nu stiu cum m-as putea revansa pentru atata ajutor pe care l-am primit pe acest forum ...

P.S. Aceasta clasa , CChildListCtrlEx evita doar necesitatea de a edita CListCtrlEx pentru a declara membrii friend clasele view derivate din CListView ... de exemplu , daca intr-un proiect mai mare in care se foloseste CListCtrlEx atat in form-uri cat si in listview-uri , in CChildListCtrlEx se declara cercul de prieteni :biggrin: , in rest nu cred ca ar fi necesara folosirea ei ...

Numai bine !!!

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 26 May 2011, 08:27
by Ovidiu Cucu
[ Split thread ]
Subiectul nou e la www.codexpert.ro/forum/viewtopic.php?f=14&t=1700

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 02 Jun 2011, 11:20
by mesajflaviu
Tot folosind acest control (CListCtrlEx) ca si control al clasei CListView am descoperit un mic bug : deturnand toate mesajele CListView catre CChildListCtrlEx nu mai am acces la timer ! Prima data sa pun aici implentarea clasei CMyListView , derivata din CListView :

Code: Select all

BOOL CTestList6View::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class

	if(! CListView::PreTranslateMessage(pMsg))
		return m_List.PreTranslateMessage(pMsg);

	return FALSE;
}

BOOL CTestList6View::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
{
	// TODO: Add your specialized code here and/or call the base class

	if(! CListView::OnChildNotify(message, wParam, lParam, pLResult))
		return m_List.OnChildNotify(message, wParam, lParam, pLResult);

	return FALSE;
}

LRESULT CTestList6View::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class

	LRESULT lResult = 0;

	if(! CListView::OnWndMsg(message, wParam, lParam, &lResult))
	{
		if(! m_List.OnWndMsg(message, wParam, lParam, &lResult))
		{
			lResult = DefWindowProc(message, wParam, lParam);
		}
	}

	return lResult;
}
si in loc sa folosesc GetListCtrl() , folosesc m_List, iar totul functioneaza de minune , cu exceptia timer-ului ...

Code: Select all

void CTestList6View::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default

	TRACE("here I use the timer\n");

	CListView::OnTimer(nIDEvent);
}
nu merge timer-ul decat o data ( un tic ) . Am incercat sa filtrez mesajele ceasului in OnPreTranslateMessage(...)

Code: Select all

BOOL CTestList6View::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class

	if(pMsg->message == WM_TIMER)return CListView::PreTranslateMessage(pMsg);

	if(! CListView::PreTranslateMessage(pMsg))
		return m_List.PreTranslateMessage(pMsg);

	return FALSE;
}
dar fara succes ... ce as putea face sa am ceas ?

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 02 Jun 2011, 16:06
by Ovidiu Cucu
In pimul rand, de ce incerci sa "deturnezi" toate mesajele lui "CTestList6View" ?

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Posted: 02 Jun 2011, 16:08
by mesajflaviu
Ovidiu Cucu wrote:In pimul rand, de ce incerci sa "deturnezi" toate mesajele lui "CTestList6View" ?
Pai cred ca asta face codul din PreTranslateMessage(...) dupa modelul articolului din codeguru ....