CWnd - HWND Verwirrung



  • Also, ich weiß, dass es Windows Klassen gibt, die HWNDs, die halt ein Fenster repräsentieren.
    Die MFC "umhüllt" das ganze ja dann mit CWnd Objekten.

    Wenn ich jetzt ein neues Steuerelement mit dem Designer von VS2008 in einem Dialog erstelle, was wird dann eigentlich erzeugt?
    Mit Sicherheit doch das HWND, welches man mit ::GetDlgItem() bekommen kann.
    Aber wird auch gleichzeitig ein CWnd Objekt erstellt, oder wie ist das?

    Ich habe auch mal gelesen, dass es für jedes HWND nur ein CWnd Objekt gibt (die werden in der, erm, "Perm Map" verwaltet).

    Was liefert dann aber eigtl. CWnd::FromHandle und CWnd::FromHandlePermanent?
    Ich nehme an, dass FromHandlePermanent halt nur in der Perm Map nachschaut, während FromHandle auch noch evtl. ein CWnd Objekt wo auch immer erzeugt.

    Wann wird ein temporäres Objekt erzeugt? Und was heißt hier eigtl. temporär (also wann wird es wieder gelöscht)?
    Und wenn ein temporäres CWnd Objekt erstellt wird, was passiert dann mit den ganzen Membervariablen? Werden die initialisiert? Und ist dieses CWnd Objekt in der MessageMap quasi eingetragen, also erhält es Nachrichten?

    Ich hab auch mal ein eigenes Steuerelement geschrieben.
    Mit dem Dialog-Designer habe ich dann so ein "Benutzerdefiniertes Steuerelement" eingefügt, und als Klassenname habe ich den Namen eingegeben, den ich dafür genommen habe. Dieser Name musste mit RegisterWndClass registriert werden.
    Das heißt doch, da habe ich dann ein HWND erstellt, da jetzt Nachrichten an meine Nachrichtenfunktion übermittelt wurden.

    Jetzt habe ich versucht, noch ein Objekt meiner von CWnd abgeleiteten Klasse zu erstellen, da ich hier die ganze Logik eingebettet habe.
    Das habe ich in der Nachrichtenbehandlungsfunktion des HWND gemacht (die ich RegisterWndClass mitgeteilt habe und die auch aufgerufen wird von Windows).
    Sprich, ich habe ja das HWND, und das habe ich einem neuen CMyWnd Objekt mit CWnd::Attach() übergeben.
    Als ich dann allerdings in meinem Dialogklasse GetDlgItem() aufrufte, waren die Membervariablen mit Müll gefüllt, und ich erhielt irgendein ASSERT nach kurzer Zeit (aber nicht sofort).
    Ich denke mal, mir wurde da ein temporäres Objekt übergeben, oder so, wobei ich nicht ganz verstehe, warum.
    (Nur so zur Info, hab die Methode aus nem Buch^^)

    Nach einigem rumprobieren und Suchen habe ich es dann dahingehen verändert, dass ich den RegisterWndClass() Aufruf in den Konstruktor meines CWnd Objekts verlegt habe. Außerdem habe ich eine Membervariable in der Dialogklasse erzeugt (also keinen Zeiger), und habe dann DDX_Control in der DoDataExchange() Funktion aufgerufen und diese Membervariable übergeben.

    Das hat geklappt, weiß nur nicht warum 😞
    Was macht DDX_Control? Wird da nicht was subgeclassed?
    Aber hier was subclassen macht finde ich keinen Sinn, da es ja genau die selben Objekte/Klassen sind?
    Als ich mir den Quellcode angeschaut habe, ist mir auch aufgefallen, das GetDlgItem() benutzt wird. Dachte, das Objekt, auf das der zurückgelieferte Zeiger zeigt kann temporär sein, da CWnd::FromHandle dazu aufgerufen wir?

    Und wie, und wo, und was??? 😕

    Sprich, ich blicke überhaupt nicht durch, wie CWnd mit HWND korrespondieren 😞



  • Hmm... CWnd ist ja die Basisklasse deines Fensters... bzw. steuerelement. HWND ist das Handle, zeiger auf das Fenster...

    Ich denke man kann sich die Fenster archtiektur wie ne Baumstruktur vorstellen, wobei die HWND die Blätter sind, welche auf das Physikalische objekt "Cwnd" im speicher zeigen...

    Aber vll. erzähl ich ja hier voll den müll^^



  • CWnd macht nichts weiter, als Operationen über den HWND ausführen. Dieser referenziert wie schon gesagt auf das Fenster (intern vermutlich auf irgendeine kryptische Windows Struktur). Das ist nichts weiter, als die WinAPI in einer praktischen Klasse zu verpacken. Du kannst ja einfach mal einen Breakpoint setzen und in die Aufrufe reinspringen. Dann wirst du sehen, das aus

    pMeinCWnd->SetWindowText("Hello World!");
    

    auch nur:

    SetWindowText(m_hWnd, "Hello World!");
    

    ...wird.

    Zum Unterschied FromHandle/FromHandlePermanent:
    FromHandle erzeugt AFAIK ein temporäres CWnd Objekt, wenn der HWND bisher mit keinem CWnd verbunden wurde, während FromHandlePermanent nur CWnd* zu verbundenen HWNDs zurückgibt.


  • Mod

    Cpp_Junky schrieb:

    Zum Unterschied FromHandle/FromHandlePermanent:
    FromHandle erzeugt AFAIK ein temporäres CWnd Objekt, wenn der HWND bisher mit keinem CWnd verbunden wurde, während FromHandlePermanent nur CWnd* zu verbundenen HWNDs zurückgibt.

    Etwas genauer:
    FromHandlePermanent liefert nur die CWnd* zurück bei denen das Fenster enweder gesubclassed wurde (in Dialogen via DoDataExchange oder SubclassDlgItem), oder die direkt per CWnd::Create erzeugt wurden.

    FromHandle schaut erst in die permanent Map. Ist dort kein Eintrag wird ein Eintrag in der temporären Map gemacht. In CWinApp::OnIdle werden temporäere Mapeinträge wieder entsorgt.
    CWnd* sollten also niemals über längere Zeit gespeichert werden, außer es handelt sich um Einträge aus der permanent map.



  • gut, so weit isses klar.

    Aber, was wird dann erstellt, wenn ich zum Beispiel eine Edit Box per VS-Designer in ein Dialogfenster einfüge?

    Und wie wird ein temporäres Objekt von FromHandle() initialisiert (member variablen, etc...)?


  • Mod

    Gugi schrieb:

    gut, so weit isses klar.

    Nein! Die Fragen zeigen, dass Dir nichts klar ist.
    🤡

    Aber, was wird dann erstellt, wenn ich zum Beispiel eine Edit Box per VS-Designer in ein Dialogfenster einfüge?

    Dan wird kein Objekt erzeugt!

    Und wie wird ein temporäres Objekt von FromHandle() initialisiert (member variablen, etc...)?

    CWnd hat keine Member Variablen! Jedenfalls keine die außer m_hWnd irgendwas mit dem Fester zu tun haben. 🕶



  • Hast Recht, mir isses klar nicht klar^^

    Also, das bedeutet: CWnd Objekte sind quasi nur dazu da, um für die Nachrichten eine objektorientierte Lösung anzubieten.
    Folglich enthalten sie (auser eben m_hWnd) keine Variablen, sondern nur Funktionen, die mehr oder weniger direkt an die WinAPI weitergegeben werden.

    Richtig?

    Das beudeutet doch dann aber, dass man gar keine Membervariablen in Fenstern haben sollte, oder nicht?



  • niemand? 😞


  • Mod

    Gugi schrieb:

    Das beudeutet doch dann aber, dass man gar keine Membervariablen in Fenstern haben sollte, oder nicht?

    Nein! Warum nicht? Die Fenster, die Membervariablen brauchen (CView, CDialog abgeleitete Klassen) werden ja auch aus der MFC heraus erzeugt.

    Es ist einfach so, dass pure (100% WinAPI Controls) keine haben UND keine brauchen. Während eigen erzeugte Controls über den Subclass Mechanismus der MFC welche dazu bekommen.



  • erm, aber wie werden dann die Membervariablen in temporären Objekten initialisiert?

    Sry, aber ich hab mir schon den source angeschaut, und checks immer noch nicht 😞


  • Mod

    Es sind normale CWnd Objekte und die werden durch das new ganz normal initialisiert.

    Denke nicht das ein Edir Control als temporäres Objekt ein CEdit bekäme, so weit geht die MSDN nicht.

    Es ist übrigends bei den Basisklassen absolut erlaubt und ungefährlich ein CWnd* nach CWEdit* zu casten weil es keine member Variablen in CEdit mehr gibt als in CWnd!


Anmelden zum Antworten