Atasare CHeaderCtrlEx la CListCtrlEx

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 19 Dec 2010, 00:27

Va asptept ! :welcome:

P.S. Sper sa nu ma intelegeti gresit , recunostinta mea nu se reduce la bere !!!
Attachments
TestList5.rar
(108.5 KiB) Downloaded 251 times



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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 12 May 2011, 21:16

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 ...
Last edited by mesajflaviu on 12 May 2011, 21:36, edited 1 time in total.

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 12 May 2011, 21:36

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 ...

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 12 May 2011, 22:07

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

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 12 May 2011, 22:39

Atasez si proiectul demo , poate cand aveti timp va uitati peste el ...
Attachments
TestList6.2.zip
(157.94 KiB) Downloaded 246 times

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by Ovidiu Cucu » 12 May 2011, 23:14

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?

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 13 May 2011, 07:57

Am testat aplicatia si fara CTestList6View::WindowProc(...) , dar la fel , aplicatia nu trece prin CListCtrlEx::WindowProc(...).

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 13 May 2011, 08:10

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)

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by Ovidiu Cucu » 13 May 2011, 12:04

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. :)

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 13 May 2011, 12:19

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 ...

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 14 May 2011, 09:36

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 !!!

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by Ovidiu Cucu » 26 May 2011, 08:27

[ Split thread ]
Subiectul nou e la www.codexpert.ro/forum/viewtopic.php?f=14&t=1700

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 02 Jun 2011, 11:20

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 ?

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by Ovidiu Cucu » 02 Jun 2011, 16:06

In pimul rand, de ce incerci sa "deturnezi" toate mesajele lui "CTestList6View" ?

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

Re: Atasare CHeaderCtrlEx la CListCtrlEx

Post by mesajflaviu » 02 Jun 2011, 16:08

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 ....

Post Reply