Problema ON_NOTIFY_REFLECT_EX
-
- Membru++
- Posts: 687
- Joined: 10 Sep 2008, 21:40
- Judet: Cluj
Re: Problema ON_NOTIFY_REFLECT_EX
Da , intradevar asta era situatia mea, CTestList6View derivata din CListViewExt , iar CListViewExt deritvata din CListView. In mod normal nu este nevoie de OnColumnClick si in parinte si in copil, dar fiindca nu functiona ON_NOTIFY_REFLECT_EX eram curios cum se poate rezolva problema ... si am vazut-o rezolvata elegant.
Daca tot am primit o solutie buna, as intreba inca ceva : in CListViewExt am cateva metode care tin de CListCtrl, de exemplu InsertItem(...), care se poate apela in CTestList6View simplu : InsertItem(...), adica fara GetListCtrl().InsertItem(...). Ok, dar nu toate metodele CListCtrl sant implementate in CListViewExt, asa ca un eventual programator nu stie cand sa apeleze metode ale CListViewExt, si cand metode CListCtrl ... De exemplu InsertItem(...) trebuie folosita ca atare si nu GetListCtrl().InsertItem(...) .... dar de exemplu SetItemText(...) nu are implementare in CListViewExt, si atunci aceasta metoda trebuie folosita GetListCtrl().SetItemText(...).
Bine, asta pentru ca totul sa fie facut cum trebuie, nu ca nu ar merge si asa ... eu am gasit o solutie, dar nu stiu daca e tocmai cea mai inspirata : am implementat in CListViewExt toate metodele CListCtrl ( care intamplator nu sant tocmai putine ) si atunci in CTestList6View se pot apela metode specifice CListCtrl fara GetListCtrl() in fata, eventual cu GetListCtrlExt() care aduce o referinta la CListViewExt.
Daca tot am primit o solutie buna, as intreba inca ceva : in CListViewExt am cateva metode care tin de CListCtrl, de exemplu InsertItem(...), care se poate apela in CTestList6View simplu : InsertItem(...), adica fara GetListCtrl().InsertItem(...). Ok, dar nu toate metodele CListCtrl sant implementate in CListViewExt, asa ca un eventual programator nu stie cand sa apeleze metode ale CListViewExt, si cand metode CListCtrl ... De exemplu InsertItem(...) trebuie folosita ca atare si nu GetListCtrl().InsertItem(...) .... dar de exemplu SetItemText(...) nu are implementare in CListViewExt, si atunci aceasta metoda trebuie folosita GetListCtrl().SetItemText(...).
Bine, asta pentru ca totul sa fie facut cum trebuie, nu ca nu ar merge si asa ... eu am gasit o solutie, dar nu stiu daca e tocmai cea mai inspirata : am implementat in CListViewExt toate metodele CListCtrl ( care intamplator nu sant tocmai putine ) si atunci in CTestList6View se pot apela metode specifice CListCtrl fara GetListCtrl() in fata, eventual cu GetListCtrlExt() care aduce o referinta la CListViewExt.
- Ovidiu Cucu
- Fondator
- Posts: 3778
- Joined: 11 Jul 2007, 16:10
- Judet: Iaşi
- Location: Iasi
- Contact:
Re: Problema ON_NOTIFY_REFLECT_EX
Nu, nu-i Ok.
Nu numai ca scrii mult cod degeaba (pui metode care pur si simplu apeleaza o alta metoda) dar mai mai sunt si alte motive:
Dimpotriva, un minus de performanta ar in cazul
...unde this->DoSomething() si this->DoSomethingElse() cheama la randul lor foo.DoSomething() si foo.DoSomethingElse().
// Ok, eu unul nu ma rup in paispe cu "performanta" la cod de genul asta, dar daca se poate simplu "mai bine", de ce nu?
NU doare mana pe nimeni sa lipeasca cu Ctrl+V toate acele "list." in cod.
Ar parea justificata "dublarea" in cazul in care ai metode de CListCtrl la care adaugi ceva in plus in CListViewExt (fac ce fac in CListViewExt apoi chem metoda corespunzatoare din CListCtrl).
Sa zicem, exemplul lui CListCtrl::InsertColumn, pe care il "dublez" cu CListViewExt::InsertColumn caruia ii mai adaug ceva argumente cu informatii suplimentare (culoare, tip (text, data,etc)) .
NU, nu-i OK. E confusing pentru cine stie cat de cat sau se uita in documentatie si in plus o poate sunta, asa cum am spus la #3.
Concluzii
Lasa asa cum e si cum se stie si cum a fost proiectat de aia ce-au facut MFC-ul! N-o fi design-ul lui "peste" si in general, lumea se prinde mai greu care-i relatia intre CListCtrl in CListView. Dar mie mi se pare destul de econimic si elegant modul cum au fost gandite.
NU te apuca sa "dublezi" metodele lui CListCtrl in CListViewExt!
Lasa-le asa cum sunt, sa fie apelate via referinta obtinuta cu GetListCtrl().
Pune in CListViewExt doar metode cu functionalitati noi!
Daca ai nevoie de argumente suplimentare nu le adauga la metodele deja existente. Pune metode noi in CListViewExt. In exemplul de mai sus, SetColumnColor, sau SetColumnData etc si NU pune o functie CListViewExt::InsertItem similara cu cea din CListCtrl dat avand argumente suplimentare.
Asa e mai clar, nu da cu barda-n ce exista, nu da nastere la confuzii si n-ai nici o frica de suntari.
Nu numai ca scrii mult cod degeaba (pui metode care pur si simplu apeleaza o alta metoda) dar mai mai sunt si alte motive:
- Daca portezi proiectul sau daca muti clasa CListViewExt in alt proiect sub o versiune mai noua de MFC ce faci? Te apuci s-o aduci la zi cu metodele noi din CListCtrl? Eu zic ca-i naspa.
- Un programator care stie clasa CListView sau se uita in documentatie, vede o singura metoda CListView::GetListCtrl si va ramane mofluz. Ce faci? Te apuci sa scrii ditamai documentatia pentru CListViewExt repetand ce scrie la CListCtrl, tinand-o la zi asa cum am spus la punctul #1? Scrii in document pur si simplu "metodele CListViewExt sunt identice cu cele din CListCtrl"? C'mon, are you sure? (see #1 again).
- La orice ora cineva poate sa-ti "sunteze" (cu voie sau din greseala) o metoda din CListViewExt cu cea din CListCtrl. Daca sa zicem, in CListViewExt ai pus si ceva in plus, a dat-o-n bara.
- si cred ca-ar mai fi...
Code: Select all
CFoo& foo = GiveMeAReferenceToFoo();
foo.DoSomething();
foo.DoSomethingElse();
// ... and so on
Code: Select all
/*this->*/DoSomething();
/*this->*/DoSomethingElse();
// ...
// Ok, eu unul nu ma rup in paispe cu "performanta" la cod de genul asta, dar daca se poate simplu "mai bine", de ce nu?
NU doare mana pe nimeni sa lipeasca cu Ctrl+V toate acele "list." in cod.
Ar parea justificata "dublarea" in cazul in care ai metode de CListCtrl la care adaugi ceva in plus in CListViewExt (fac ce fac in CListViewExt apoi chem metoda corespunzatoare din CListCtrl).
Sa zicem, exemplul lui CListCtrl::InsertColumn, pe care il "dublez" cu CListViewExt::InsertColumn caruia ii mai adaug ceva argumente cu informatii suplimentare (culoare, tip (text, data,etc)) .
NU, nu-i OK. E confusing pentru cine stie cat de cat sau se uita in documentatie si in plus o poate sunta, asa cum am spus la #3.
Concluzii
Lasa asa cum e si cum se stie si cum a fost proiectat de aia ce-au facut MFC-ul! N-o fi design-ul lui "peste" si in general, lumea se prinde mai greu care-i relatia intre CListCtrl in CListView. Dar mie mi se pare destul de econimic si elegant modul cum au fost gandite.
NU te apuca sa "dublezi" metodele lui CListCtrl in CListViewExt!
Lasa-le asa cum sunt, sa fie apelate via referinta obtinuta cu GetListCtrl().
Pune in CListViewExt doar metode cu functionalitati noi!
Daca ai nevoie de argumente suplimentare nu le adauga la metodele deja existente. Pune metode noi in CListViewExt. In exemplul de mai sus, SetColumnColor, sau SetColumnData etc si NU pune o functie CListViewExt::InsertItem similara cu cea din CListCtrl dat avand argumente suplimentare.
Asa e mai clar, nu da cu barda-n ce exista, nu da nastere la confuzii si n-ai nici o frica de suntari.
Ovidiu
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
-
- Membru++
- Posts: 687
- Joined: 10 Sep 2008, 21:40
- Judet: Cluj
Re: Problema ON_NOTIFY_REFLECT_EX
Era nevoie doar de cateva metode ale clasei CListViewExt care au acelasi nume si functionalitate ca si ale clasei CListCtrl, InsertColumn, InsertItem, DeleteColumn, DeleteItem, etc. ... le-am pus in coada cate un Ext ... si parca nu mai e asa ceata ... Asa, cu GetListCtrlExt(). am metode ale clasei CListViewExt si cu GetListCtrl(). am metode ale clasei CListCtrl.
- Ovidiu Cucu
- Fondator
- Posts: 3778
- Joined: 11 Jul 2007, 16:10
- Judet: Iaşi
- Location: Iasi
- Contact:
Re: Problema ON_NOTIFY_REFLECT_EX
Aici, parca-parca o mica diagrama de clase ar fi necesara ca sa intelegem...
. Incerc totusi in cuvinte.
Pana la urma eu as face asa:
Derivez totusi o clasa CListCtrlExt din CListCtrl, careia ii adaug metodele necesare.
"Ascund" CListView::GetListCtrl in CListViewExt. Cu alte cuvinte definesc o metoda CListViewExt::GetListCtrl:
Odata ce CListCtrlExt mosteneste CListCtrl, in CListViewExt nu este nevoie de o metoda noua CListViewExt::GetListCtrlExt (cu Ext in coada).
Ma mult incurca. Sper ca m-am exprimat suficient de clar, fara patratele si sagetute UML.
Alta cale ar fi cea pe care mersesem pana acum:
Nu mai derivez din CListCtrl si pun metodele noi direct in CListViewExt. In cazul asta, nici acel GetListCtrlExt si nici redefinirea lui GetListCtrl n-ar avea absolut nici un sens.
// Ambele ar face un architect care habar n-are Windows/MFC sa faca infarct privind la acel cast din GetListCtrl si cautand o legatura intre CListView si CListCtrl (respectiv CListViewEx si CListCtrlEx) ca sa puna sagetute pe diagrama.

Pana la urma eu as face asa:
Derivez totusi o clasa CListCtrlExt din CListCtrl, careia ii adaug metodele necesare.
"Ascund" CListView::GetListCtrl in CListViewExt. Cu alte cuvinte definesc o metoda CListViewExt::GetListCtrl:
Code: Select all
inline CListCtrlExt& CListViewExt::GetListCtrl() const
{ return *(CListCtrlEx*)this; }
Ma mult incurca. Sper ca m-am exprimat suficient de clar, fara patratele si sagetute UML.

Alta cale ar fi cea pe care mersesem pana acum:
Nu mai derivez din CListCtrl si pun metodele noi direct in CListViewExt. In cazul asta, nici acel GetListCtrlExt si nici redefinirea lui GetListCtrl n-ar avea absolut nici un sens.
// Ambele ar face un architect care habar n-are Windows/MFC sa faca infarct privind la acel cast din GetListCtrl si cautand o legatura intre CListView si CListCtrl (respectiv CListViewEx si CListCtrlEx) ca sa puna sagetute pe diagrama.

Ovidiu
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
-
- Membru++
- Posts: 687
- Joined: 10 Sep 2008, 21:40
- Judet: Cluj
Re: Problema ON_NOTIFY_REFLECT_EX
Desi ar fi mai buna, prima metoda nu stiu daca functioneaza :
... am atasat proiectul de test.
Code: Select all
// ListViewExt.h
inline CListCtrlExt& CListViewExt::GetListCtrl() const
{return *(CListCtrlExt*)this;}
- Attachments
-
- TestList.rar
- (123.11 KiB) Downloaded 277 times
- Ovidiu Cucu
- Fondator
- Posts: 3778
- Joined: 11 Jul 2007, 16:10
- Judet: Iaşi
- Location: Iasi
- Contact:
Re: Problema ON_NOTIFY_REFLECT_EX
Intai si-ntai, incearca te rog programelul urmator care simuleaza fenta cu GetListCtrl.
Merge? N-are de ce sa nu mearga.
Acuma hai sa "perfectionam" pe CFoo si sa-l facem pe CFoo::foo() virtual.
Mai merge? Mai merge dar prin balarii. 
La fel ai facut si tu cu gasca aia de functii CListCtrlExt::InsertColumn s.a.m.d.
Trebuie sa fie virtuale? Nu. Sterge repede "virtual" de acolo.
Code: Select all
#include <iostream>
struct CFoo
{
void foo() { std::cout << "Wuz ere!"; }
};
struct CBar
{
CFoo& GetFoo() { return *(CFoo*)this; }
};
int main()
{
CBar bar;
bar.GetFoo().foo();
return 0;
}
Acuma hai sa "perfectionam" pe CFoo si sa-l facem pe CFoo::foo() virtual.
Code: Select all
struct CFoo
{
virtual void foo() { std::cout << "Wuz ere!"; }
};
// ... la fel ca mai sus

La fel ai facut si tu cu gasca aia de functii CListCtrlExt::InsertColumn s.a.m.d.
Trebuie sa fie virtuale? Nu. Sterge repede "virtual" de acolo.

Ovidiu
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
- Ovidiu Cucu
- Fondator
- Posts: 3778
- Joined: 11 Jul 2007, 16:10
- Judet: Iaşi
- Location: Iasi
- Contact:
Re: Problema ON_NOTIFY_REFLECT_EX
La Biblia C++ scrie asa
Naspa daca ne luam dupa scripturi, dar in practica functioneaza atata timp cat GetListCtrl().DoSomething() nu se atinge de vreo data membru din CListCtrl si nu este virtuala.
Cum spuneam, metodele lui CListView sunt in general simple wrappere peste SendMessage deci no problem.
Ok. Acum scotand 'virtual' de acolo tot nu rezolvi problema.
Ai pus m_HeaderCtrl.SubclassWindow(hWnd) in CListCtrlExt::PreSubclassWindow care nu se apeleaza niciodata. Si mai naspa. N-o sa mearga nici chiar daca in CListViewExt apelezi direct GetListCtrl().SubclassWindow(). De ce? Pentru ca PreSubclassWindow e... virtuala de la mama ei, CWnd.
Asa ca, sa nu ne mai invartim in jurul cozii si sa ne apucam de versiunea 2 (de fapt cea pe care am recomandat-o de la inceput):
Este exact ce face MFC-ul cu acel CListView::GetListCtrl.
9.3.1 Nonstatic member functions
[...]
If a nonstatic member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined.
Naspa daca ne luam dupa scripturi, dar in practica functioneaza atata timp cat GetListCtrl().DoSomething() nu se atinge de vreo data membru din CListCtrl si nu este virtuala.
Cum spuneam, metodele lui CListView sunt in general simple wrappere peste SendMessage deci no problem.
Ok. Acum scotand 'virtual' de acolo tot nu rezolvi problema.
Ai pus m_HeaderCtrl.SubclassWindow(hWnd) in CListCtrlExt::PreSubclassWindow care nu se apeleaza niciodata. Si mai naspa. N-o sa mearga nici chiar daca in CListViewExt apelezi direct GetListCtrl().SubclassWindow(). De ce? Pentru ca PreSubclassWindow e... virtuala de la mama ei, CWnd.
Asa ca, sa nu ne mai invartim in jurul cozii si sa ne apucam de versiunea 2 (de fapt cea pe care am recomandat-o de la inceput):
// daca o sa ai un pic de rabdare, poate termin un schelet in proiectul ListOne care sa te ajute sa vezi ce si cum trebuie facut.Nu mai derivam din CListCtrl si pun metodele noi direct in CListViewExt.
Ovidiu
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
-
- Membru++
- Posts: 687
- Joined: 10 Sep 2008, 21:40
- Judet: Cluj
Re: Problema ON_NOTIFY_REFLECT_EX
Asta am incercat si euAi pus m_HeaderCtrl.SubclassWindow(hWnd) in CListCtrlExt::PreSubclassWindow care nu se apeleaza niciodata. Si mai naspa. N-o sa mearga nici chiar daca in CListViewExt apelezi direct GetListCtrl().SubclassWindow().

- Ovidiu Cucu
- Fondator
- Posts: 3778
- Joined: 11 Jul 2007, 16:10
- Judet: Iaşi
- Location: Iasi
- Contact:
Re: Problema ON_NOTIFY_REFLECT_EX
Am pus un demo cu rezolvarile aici: http://www.codexpert.ro/forum/viewtopic.php?f=14&t=1784
Ovidiu
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks
Follow http://twitter.com/#!/ovidiucucu
Weblog: http://codexpert.ro/blog/author/ovidiu-cucu/
Visit FAQ, Tips & Tricks