Benutzer mit den meisten Antworten
EnumChildWindows / EnumChildProc findet mehr als gedacht

Frage
-
VS2011, Win Vista 32, MFC-Projekt
folgendes wurde hier beobachtet, beim Versuch, alle Controls innerhalb eines CFormViews einzusammeln:
CMyForm::OnInitialUpdate(){ //dynamisch ein paar Controls per COleControl::CreateControl erzeugen. //CSPCCtrlLabel ist ein eigenes OCX. Das Rect des Controls ist absichtlich nicht //vernünftig angegeben, das wird später berechnet CSPCCtrlLabel* lb11 = new CSPCCtrlLabel(); lb11->CreateControl(lb11.GetClsid(), NULL, WS_VISIBLE, CRect(), this, 5000); CSPCCtrlLabel* lb12 = new CSPCCtrlLabel(); lb12->CreateControl(lb12.GetClsid(), NULL, WS_VISIBLE, CRect(), this, 5001); //usw. es werden noch weitere Controls vom gleichen Typ nach gleichen Muster erzeugt //diese sollen jetzt per EnumChildWindows eingesammelt und dann später resized usw. werden EnumChildWindows( m_hWnd, (WNDENUMPROC) EnumChildProc, (LPARAM) (&_arrControls)); //Hier erwarte ich jetzt alle Controls (die oben erzeugten und die im Ressourceneditor angelegten) //in _arrControls for (int i=0; i<_arrControls.GetSize(); i++){ CWnd* pWnd = GetDlgItem(_arrControls[i]); ASSERT(pWnd != NULL); //SCHLÄGT ZU??? } } /*static*/ BOOL CALLBACK CMyForm::EnumChildProc(HWND hwnd, LPARAM lParam) { CArray<int, int> *pData= (CArray<int, int>*) lParam; CWnd *pWnd = CWnd::FromHandle(hwnd); ASSERT(pWnd != NULL, _T("CWnd zu Handle %d ist null?"), hwnd); int iIdControl = pWnd->GetDlgCtrlID(); int idWindow = GetWindowLong(hwnd, GWL_ID); //Debugsausgaben //(1) CRuntimeClass* prt = pWnd->GetRuntimeClass(); TRACE(_T("iIdControl: %d, idWindow: %d, '%hs'"), iId, idChild, prt->m_lpszClassName); pData->Add(iIdControl); return TRUE; }
(1) der Trace aus EnumChildProc liefert ungefähr folgende Ausgaben:
iIdControl: 5001, idWindow: 168018000, 'CSPCCtrlLabel'
iIdControl: 5002, idWindow: 168016480, 'CSPCCtrlLabel'
iIdControl: 1104, idWindow: 167966144, 'CSPCRegelkarte'
iIdControl: 46850920, idWindow: 46850920, 'CWnd'
iIdControl: 166435656, idWindow: 166435656, 'CWnd'
iIdControl: 0, idWindow: 0, 'CWnd'
die ersten 3 Ausgaben finde ich auch noch absolut verständlich: 1 und 2 sind die dynamisch angelegten Labels, direkt vor EnumChildWindows, 3. ist ein statisch im Ressourceneditor auf das Form gepackte OCX. Weitere statische Controls gibts es nicht!
Woher kommen denn die Tracezeilen 4-6? der versuch, GetDlgItem mit diesen IDs aufzurifen, liefert mir auch jedesmal NULL zurück. 0 bzw. derartig große IDs gibt es auch nirgends in der Resource.h.
bin dankbar für hinweise
micha
Antworten
-
Ich vermute das sind Fenster die zu Deinem OCX Control gehören.
Schau Dir das ganze im Spy++ an! OCX kochen auch nur mit Wasser und sind oft genug auch Fenster, aber nicht immer ;)BTW1: Warum machst Du das so kompliziert mit EumChildWindows? Mit der Funktion GetWindow, ist das viel einfacher die Fensterhierarchie zu durchlaufen.
BTW2: CWnd::FromHandle wird Dir immer ein Control liefern für alle Fenster, auch die Du nicht erzeugt hast (eben über ein temporäres CWnd Objekt). Mit FromHandlePermanent bekommst Du exakt die Controls, die Du angelegt oder gesubclassed hast.
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort markiert suriel6666 Donnerstag, 10. November 2011 10:35
Alle Antworten
-
Ich vermute das sind Fenster die zu Deinem OCX Control gehören.
Schau Dir das ganze im Spy++ an! OCX kochen auch nur mit Wasser und sind oft genug auch Fenster, aber nicht immer ;)BTW1: Warum machst Du das so kompliziert mit EumChildWindows? Mit der Funktion GetWindow, ist das viel einfacher die Fensterhierarchie zu durchlaufen.
BTW2: CWnd::FromHandle wird Dir immer ein Control liefern für alle Fenster, auch die Du nicht erzeugt hast (eben über ein temporäres CWnd Objekt). Mit FromHandlePermanent bekommst Du exakt die Controls, die Du angelegt oder gesubclassed hast.
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de- Als Antwort markiert suriel6666 Donnerstag, 10. November 2011 10:35
-
> vermute das sind Fenster die zu Deinem OCX Control gehören
du vermutest auf jeden fall richtig, daß das ocx selbst noch fenster erzeugt, ja. wusste nur nicht, daß die ebenfalls mit eingesammelt werden.
> Mit FromHandlePermanent bekommst Du exakt die Controls, die Du angelegt oder
> gesubclassed hast
ja, seltsam, seltsam, zumindest für mich ;-)
FromHandlePermanent liefert mir tatsächlich "weniger", aber leider auch nicht mehr das bitmap, daß ich im ressourceneditor aufs form gepackt, aber in DoDataExchange nicht explizit mit einem member verbunden habe.
wenn ich alles auf GetWindow umstelle (was ich jetzt getan habe), seiht es tatsächlich so aus wie gewünscht: ich bekomme nicht die Fenster, die das ocx erstellt, das bitmap allerdings schon.
also es hilft mir so weiter, danke für die info, aber identisches verhalten zwischen GetWindow und EnumChildWindows ist das irgendwie nicht. quasi "glück gehabt"
-
> also es hilft mir so weiter, danke für die info, aber identisches verhalten zwischen GetWindow und EnumChildWindows ist das irgendwie nicht. quasi "glück gehabt"
Ich glaube Du unterliegst da einem Irrtum, aber ich arbeite nie mit EnumChildWindows weil mir das viel zu kompliziert ist und GetWindow alles viel einfacher unterstützt.Ich glaube eher, dass EnumChildWindows auch rekursiv in die Tiefe geht, was GetWindow nicht macht. Es liefert Dir genau eine Ebene, wenn Du mit dem ersten Child anfängst GW_CHILD und dann die nächsten abfragst GW_NEXT.
Wie ich schon geschrieben habe: Schau Dir die Struktur in Spy++ an!
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de