[T] Klassen der MFC: CWnd
-
Was ist CWnd?
CWnd ist eine Klasse, die man in der GUI-Programmierung eigentlich ständig benutzt, aber es selten bemerkt.
CWnd ist ein Fenster. Nicht in dem Sinne wie ein Programmfenster mit Menü und Titelzeile, sondern die Basis dafür und für viele andere Dinge, die man so zu sehen bekommt.Da auf CWnd so viel aufbaut, ist es sinnvoll sich zumindest mit einigen Funktionen vertraut zu machen. Die anderen kann man ja immer noch in der MSDN nachschlagen.
Häufig genutzte Funktionen
De-/Aktivieren
EnableWindow aktiviert bzw. deaktiviert das Fenster für Eingaben.
pWnd->EnableWindow(TRUE); // Aktiviert das Fenster pWnd->EnableWindow(FALSE); // Deaktiviert das Fenster
Mit IsWindowEnabled kann man abfragen, ob das Fenster gerade aktiv ist oder nicht.
Verstecken oder Anzeigen
Mit ShowWindow kann man ein Fenster verstecken oder anzeigen.
Wenn es das Hauptfenster des Programms ist, kann man noch mehr machen, aber das steht alles in der MSDN.GetDlgItem(IDC_IRGENDWAS)->ShowWindow(SW_HIDE); // Fenster verstecken GetDlgItem(IDC_IRGENDWAS)->ShowWindow(SW_SHOW); // Fenster anzeigen
Focus
SetFocus setzt den Focus (die Eingabemarke) auf das Fenster.
GetFocus gibt zurück, welches Fenster den Focus hat.pWnd->SetFocus(); // Focus setzen CWnd* pOther = GetFocus(); // Focus abfragen _ASSERTE(pWnd == pOther); // Es muss gleich sein, wir haben ja zwischendrin nichts ungesetzt.
Fensterposition
GetWindowRect gibt die Koordinaten des Fenstern auf dem Bildschirm (Screen-Koordinaten) zurück.
MoveWindow verschiebt das Fenster an die gegebenen Client-Koordinaten.
Da der Ursprung bei Client-Koordinaten (die linke obere Ecke des Fensters) selten der selbe ist wie bei Screen-Koordinaten (die linke obere Ecke des Monitors), muss man mit ScreenToClient umrechnen.
Dieser "Koordinaten-Konflikt" tritt häufig auf. Falls also die Fenster nicht dort angezeigt werden, wo man sie erwartet, sollte man prüfen ob eine Umrechnung nötig ist.CRect rect; // Zum Zwischenspeichern GetDlgItem(IDC_IRGENDWAS)->GetWindowRect(&rect); // Koordinaten holen ScreenToClient(&rect); // Koordinaten umrechnen GetDlgItem(IDC_IRGENDWAS_ANDERES)->MoveWindow(&rect); // Fensterposition festlegen
Fenstertext / Beschriftung
GetWindowText füllt einen gegebenen CString mit der Beschriftung des Wnd.
Bei einem Dialog ist es der Fenstertitel, bei einem Edit die Usereingabe, bei einer Checkbox die Beschriftung usw.
Mit SetWindowText kann man den Text festlegen.CString strWndText; // Zum Zwischenspeichern GetDlgItem(IDC_IRGENDWAS)->GetWindowText(strWndText); // Die Beschriftung holen AfxMessageBox(strWndText); // Kontrollausgabe GetDlgItem(IDC_IRGENDWAS)->SetWindowText(_T("Blabla ;)")); // Eine andere Beschriftung festlegen.
Eine andere Möglichkeit sind GetDlgItemText und SetDlgItemText oder GetDlgItemInt und SetDlgItemInt.
Schriftart
GetFont gibt die aktuelle Schriftart als CFont* zurück.
Diese kann man nun nach Belieben verändern und mit SetFont wieder zuweisen.
Dabei ist allerdings zu beachten, dass der zugewisene Font eine Membervariable z.B. des Parent-Dialoges oder wenn man eine eigene Klasse hat auch die des Wnd sein muss, sonst bleibt der Code scheinbar wirkungslos.
// Im Header CFont m_fontFett;
// Im cpp LOGFONT lf; // Hilfsvariable CFont* font = GetDlgItem(IDC_EDT_IRGENDWAS)->GetFont(); // Den aktuellen Font holen if (font) // Wenn das geklappt hat { font->GetLogFont(&lf); // Font in die Hilfsvariable übertragen lf.lfWeight = FW_BOLD; // Fett aktivieren m_fontFett.CreateFontIndirect(&lf); // den endgültigen Font erstellen GetDlgItem(IDC_EDT_IRGENDWAS)->SetFont(&m_fontFett); // Font festlegen }
Farben
Die Farben (Vordergrund und Hintergrund) kann man leider nicht so einfach mit z.B. SetBkColor festlegen - es sei denn, man baut sich diese Funktion in eine eigene Wnd-Klasse ein.
Um die Farben zu ändern, muss man sich um die Nachricht WM_CTL_COLOR kümmern, die Funktion dazu heißt OnCtlColor.
Meistens ist diese Funktion im Parent-Dialog und behandelt mehrere Child-Wnd auf einmal.
Eine nützliche Funktion in diesem Zusammenhang ist GetSysColor, mit der man die vom Benutzer eingestellten Farben abfragen kann.HBRUSH CMyView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor); // Basisklasse aufrufen // Dieses Control soll eine rote Schrift haben if (pWnd->GetDlgCtrlID() == IDC_EDT_DASDA) { pDC->SetTextColor(RGB(255, 0, 0)); // Schriftfarbe festlegen pDC->SetBkMode(TRANSPARENT); HBRUSH B = CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); //Hintergrundfarbe soll die im System eingestellte sein return (HBRUSH) B; } return hbr; }
Welches Kriterium man nimmt um die Färbung zu unterscheiden ist eigentlich nur der eigenen Fantasie überlassen, man kann durchaus auch alle Edits blau und alle Buttons grün machen.
-
So, jetzt brauche ich eure Hilfe: Fehlt da noch was?
Es sollen nicht alle Funktionen beschrieben werden, dazu habe ich die MSDN verlinkt.
Aber so die typischen Anfängerfragen und ganz alltägliche Sachen möchte ich schon drin haben.
-
Puh, auffallen tut mir so direkt nix. Ist auch länger her das ich da was gemacht habe mit MFC.
Ausser diesem hier:
_ASSERTE(pWnd == pOther); // Es muss gleich sein, wir haben ja zwischendrin nichts ungesetzt.
Ist das so korrekt, oder nutzt du die italienische Version von MSVC?
ps. ich würde übrigens zu wxWidgets oder QT raten :p
-
Ich hätte eine etwas ausführlichere Erklärung erwartet, was unter MFC alles als "Fenster" durchgeht - der eine Satz dort oben ist etwas knapp gehalten (selbst mit dem Link zur MFC-Klassenhierarchie).
-
phlox81 schrieb:
Puh, auffallen tut mir so direkt nix. Ist auch länger her das ich da was gemacht habe mit MFC.
Ausser diesem hier:
_ASSERTE(pWnd == pOther); // Es muss gleich sein, wir haben ja zwischendrin nichts ungesetzt.
Ist das so korrekt, oder nutzt du die italienische Version von MSVC?
Das ist korrekt, dieses "ASSERT" habe ich auch erst neulich im Forum entdeckt, da wird in der Messagebox gleich noch das in den Klammern (die Bedingung) ausgegeben. Sehr praktisch um schon an der Meldung zu sehen wodrum es geht.
ps. ich würde übrigens zu wxWidgets oder QT raten :p
Die Diskussion lassen wir lieber, hier gehts um MFC - für die anderen gibts andere Artikel.
CStoll schrieb:
Ich hätte eine etwas ausführlichere Erklärung erwartet, was unter MFC alles als "Fenster" durchgeht - der eine Satz dort oben ist etwas knapp gehalten (selbst mit dem Link zur MFC-Klassenhierarchie).
Ich hatte auch eine ausführlichere Erklärung vor, aber mir fällt keine ein.
Ich benutz den Kram zwar ständig aber ich krieg es nicht erklärt.Hättest du nen Satz parat oder ein, zwei Links aus denen man sich einen Satz erlesen kann? (Nein, ich will nicht kopieren!)
-
Ich würde ja eine kurze (unvollständige) Liste anhängen, was alles als "Fenster" durchgeht (Dialoge, Dialog-Elemente, Symbolleisten, etc). Eine ausführlichere Erklärung hätte ich auch, allerdings auf die Schnelle nur in der Offline-Version der MSDN.
*geht suchen* Ich hab's doch gefunden: derived Window Classes.
-
CStoll schrieb:
Ich würde ja eine kurze (unvollständige) Liste anhängen, was alles als "Fenster" durchgeht (Dialoge, Dialog-Elemente, Symbolleisten, etc). Eine ausführlichere Erklärung hätte ich auch, allerdings auf die Schnelle nur in der Offline-Version der MSDN.
Okay das werde ich noch ergänzen.
*geht suchen* Ich hab's doch gefunden: derived Window Classes.
Da kommt "Content not found".
Aber meine MSDN kennt das zum Glück auch.PS: Da ist der richtige Link: http://msdn2.microsoft.com/en-us/library/f3a0a96e.aspx
Ah, das ist der von dir, aber du bist mit den url-Tags durcheinandergeraten.
-
estartu schrieb:
*geht suchen* Ich hab's doch gefunden: derived Window Classes.
Da kommt "Content not found".
Aber meine MSDN kennt das zum Glück auch.Grml - das passiert, wenn man nicht mit den url-Tags zurechtkommt
-
Was ich in so einem Artikel interessant fände, wenn du zeigen könntest wie man z.B. ein einfaches MFC-Fenster mit mehreren Steuerelementen (z.B. auch wieder Child-Fenster) per Hand (also selbst coden) anlegt. Würde bestimmt auch das Verständnis fördern und die Zusammenhänge gut aufzeigen. Ausserdem ist das meines Wissens nicht so intuitiv einfach wie z.B. unter anderen GUI-Frameworks, da die Win-API halt doch nicht sehr weit weg abstrahiert ist...
-
nep schrieb:
Was ich in so einem Artikel interessant fände, wenn du zeigen könntest wie man z.B. ein einfaches MFC-Fenster mit mehreren Steuerelementen (z.B. auch wieder Child-Fenster) per Hand (also selbst coden) anlegt. Würde bestimmt auch das Verständnis fördern und die Zusammenhänge gut aufzeigen. Ausserdem ist das meines Wissens nicht so intuitiv einfach wie z.B. unter anderen GUI-Frameworks, da die Win-API halt doch nicht sehr weit weg abstrahiert ist...
Das fände ich auch sehr interessant.
Allerdings gibt es da einen Haken: Das habe ich noch nie gemacht.Ich würde das zu gerne mit aufnehmen, einmal um meine Wissenslücke zu schließen und um die bei anderen auch zu verhindern. Allerdings bräuchte ich da endgültig Hilfe.
-
-
Du hast nach einer Defintion von CWnd gefragt. Wie wäre es hiermit:
Unter einem CWnd versteht man alles was weitläufig als Fenster bezeichnet werden kann (daher auch der Name Window). Ein Fenster ist ein meist rechteckiges Steuerelement welches auf dem Bildschirm dargestellt wird und sich um die Benutzerinteraktion kümmert.
Da der Platz auf dem Bildschirm beschränkt ist sind Fenster in einer Hierarchie geordnet. Wird das Elternfenster nicht angezeigt so wird auch keines der Kinder welche sich meisten in dem Zeichenrechteck des Elternfenster befinden angezeigt.
Der Desktop ist auch ein Fenster, wenn auch ein wenig magisch da es kein Elternfenster besitzt.
Beispiel: Minimiert man das Hauptfenster einer Anwendung so werden auch die Buttons in diesem Fenster nicht mehr angezeigt da es sich um Kinder handelt.
Bei anderen GUI Toolkits werden Fenster auch noch Control (ctrl) oder auch Widgets genannt.
-
Das gefällt mir.