|
|
|
|
|
| Bevor wir mit der Beschreibung der Fensterklassen beginnen, wollen wir
erst einmal dafür sorgen, dass wir in Zukunft auch die gleiche Sprache sprechen. Wenn im Folgenden der Begriff Fensterklasse verwendet wird so sind damit die durch die MFC bereitgestellten Fensterklassen wie z.B. CWnd gemeint. Wenn Bezug auf die WINDOWS Fensterklasse (Stichwort: RegisterClassEx(...)) genommen wird, so wird dies ausdrücklich erwähnt. Der Begriff Fenster wird immer für das durch WINDOWS verwaltete Fenster verwendet. Fensterobjekte hingegen bezeichnen C++ Objekte, welche in der Regel im Programmverlauf mit einem Fenster verknüpft werden. Diese Verknüpfung geschieht über die Membervariable m_hWnd des Fensterobjektes die das zum Fenster gehörende Fenster-Handle enthält.
|
Die Klasse CWnd stellt für die Anwendung die Schnittstelle dar, über die sie das WINDOWS Fenster beeinflussen kann. D.h. die Klasse CWnd, oder eine davon abgeleitete Klasse, kapselt viele der API-Funktionen die sich mit der Fenstersteuerung befassen. Sie besitzt eine schier unüberschaubare Anzahl von Methoden zur Fenstersteuerung. Sie können sich nun eine Kurzübersicht der Klasse CWnd ansehen um einen Überblick über die wichtigsten Methoden dieser Klasse zu erhalten.
In der Regel wird für das Hauptfenster der Anwendung nicht direkt ein CWnd-Objekt verwendet sondern ein Objekt einer von CWnd abgeleiteten Klasse. Für unsere ersten Schritte verwenden wir als Hauptfenster ein Objekt der Klasse CFrameWnd. Die Klasse CFrameWnd erweitert die Eigenschaften der Klasse CWnd z.B. um eine Titelzeile oder auch um die Möglichkeit dem Fenster ein Menü hinzuzufügen.
Um das Hauptfenster einer Anwendung zu erstellen sind folgende Schritte durchzuführen:
Aber merken Sie sich folgenden wichtigen Satz:
| Die alleinige Erstellung eines Fensterobjektes erstellt noch kein Fenster sondern erzeugt nur eine entsprechende Datenstruktur! |
Bleibt zum Schluss nur noch die Frage, wann bzw. wo das Hauptfenster der Anwendung erstellt wird. Erinnern Sie sich an die vorherige Lektion über die Anwendungsklasse? Dort wurde die CWinApp Methode InitInstance(...) eingeführt. Und in dieser Methode wird das Hauptfenster der Anwendung erstellt.
| Erstellen Sie das Fensterobjekt für das Hauptfenster immer dynamisch.
d.h. mittels des new-Operators! Würde das Fensterobjekt als lokales Objekt
erstellt werden, so würde das Objekt beim Verlassen der Methode zerstört werden. Dieses
Zerstören des Fensterobjekte hätte dann zur Folge, dass auch das Fenster zerstört
würde und die Anwendung besäße kein Fenster mehr. Außerdem dürfen Sie auch niemals vergessen den Zeiger auf das Fensterobjekt der Membervariable m_pMainWnd des Anwendungsobjektes zuzuweisen. Denn nur über diese Membervariable wird das Fensterobjekt mit dem Anwendungsobjekt verbunden. |
Fügen wir jetzt unserem Beispiel ein einfaches Hauptfenster hinzu.
| Laden Sie nun das Beispiel aus der vorherigen Lektion und gehen Sie dann
in die Klassenansicht. Wenn Sie vorhin alles richtig eingegeben haben sollte die Klasse CMyApp
wie folgt aussehen:
Führen Sie einen Doppelklick auf die Methode InitInstance(...) im Klassenbaum aus um die Methode im Editorfenster anzuzeigen. Diese leere Methode gilt es nun auszufüllen. Erstellen Sie in InitInstance(...) im ersten Schritt eine Hauptfenster vom Typ CFrameWnd. Die dazu notwendigen Schritte haben Sie ja weiter oben bereits kennen gelernt. Erst im nächsten Schritt werden wir dann für das Hauptfenster eine eigene Fensterklasse verwenden.
|
Im nächsten Schritt werden wir für das Hauptfenster eine eigene WINDOWS Fensterklasse registrieren.
Erstellen Sie für das Hauptfenster eine Fensterklasse mit den folgenden
Eigenschaften:
Verwenden Sie für die Registrierung der WINDOWS Fensterklasse die oben aufgeführte Funktion AfxRegisterWndClass(...). Aber Achtung! Falls Sie nachher noch ein klein wenig mit dem Fenster herumspielen, verwenden Sie auf keinen Fall den Fesnterstil CS_NOCLOSE! Sie haben sonst keine Möglichkeit, außer dem berühmten Dreifinger-Griff <STRG>-<ALT>-<ENTF>, die Anwendung zu beenden. Beachten Sie, dass Sie den Aufruf der Methoden Create(...) jetzt noch etwas anpassen müssen!
Wenn Sie die Übung eingegeben haben, übersetzen und starten Sie das Beispiel. Sehen Sie sich dann den Fensterinhalt an! Verschieben Sie das Fenster und ändern auch einmal dessen Größe. |
Was passiert hier mit dem Fenster? Nun, da wir außer dem Fensterklassenstil alle anderen Parameter auf dem Defaultwert belassen haben, haben wir ein Fenster ohne Hintergrund, d.h. das Fenster ist sozusagen transparent. Wenn Sie das Fenster verschieben, so bleibt der bisherige Inhalt weiterhin bestehen da das Verschieben eines Fensters keine WM_PAINT Nachricht auslöst. Sie wissen doch hoffentlich noch aus dem vorherigen Kapitel den Zweck dieser Nachricht? Wenn nicht, so klicken Sie hier.
Definieren wir im nächsten Schritt die restlichen WINDOWS Fensterklassen-Eigenschaften. Was uns zu unserem Glück noch fehlt ist ein Cursor- bzw. Icon-Handle und ein Handle auf den Brush, mit dem der Fensterhintergrund auszufüllen ist.
Um einen Cursor zu laden stehen unter der MFC die beiden CWinApp Methoden LoadCursor(...) und LoadStandardCursor(...) zur Verfügung. Die erste Methode dient zum Laden eines Cursors aus einer Ressource und die zweite zum Laden eines von WINDOWS vordefinierten Standard-Cursors. Genau gleich funktioniert auch das Laden des Icons. Auch hier gibt es zwei entsprechende Methoden LoadIcon(...) und LoadStandardIcon(...). Alle vier Methoden liefern ein Handle auf den geladenen Cursor bzw. auf das geladene Icon zurück. Etwas anders verhält es sich mit dem Brush-Handle für den Fensterhintergrund. Bis wir einen eigenen Brush erzeugen können, müssen Sie hier die API-Funktion GetStockObject(...) aufrufen. Dies Funktion wurde schon im vorherigen Kapitel behandelt. Sie können sich jedoch durch anklicken des Funktionsnamens nochmals eine Beschreibung der Funktion ansehen.
| Da Ressourcen und Brushs erst in späteren Kapiteln behandelt werden stehen für unser Beispiel nur die Standard-Ressourcen zur Verfügung. |
Erstellen Sie für das Hauptfenster nun eine WINDOWS Fensterklasse mit
den folgenden Eigenschaften:
Wenn Sie das Beispiel nun starten erhalten Sie ein Fenster mit den gewünschten Eigenschaften. |
Erweitern wir das Beispiel nun um eine eigene (C++) Fensterklasse für das Hauptfenster. Die Fensterklasse wird, wie schon erwähnt, im einfachsten Fall von der Klasse CFrameWnd abgeleitet.
| Um jetzt eine neue Klasse zum Projekt hinzuzufügen, klicken Sie mit der
rechten Maustaste in der Klassenansicht den Eintrag MFCBasis Klassen an. Im
eingeblendeten Kontextmenü wählen Sie den Eintrag Neue Klasse... aus woraufhin
wieder folgender Dialog erscheint:
Nehmen Sie die oben angegebenen Einstellungen vor und klicken Sie dann den OK Button an. Auch hier schließen den darauf folgenden Hinweis auf die fehlende Headerdatei über den Ok-Button. Zum Projekt wurde jetzt die Klasse CMainWnd für das Hauptfenster hinzugefügt. Die Klassendeklaration und Methodendefinitionen befinden sich in den Dateien MainWnd.h bzw. MainWnd.cpp. Verwenden Sie jetzt als Fensterobjekt ein Objekt der soeben nur erstellten Klasse.
|
Sie könnten das Beispiel jetzt übersetzen und starten, würden jedoch noch keinen Unterschied zum vorherigen Programm sehen. Wir werden jetzt noch etwas mit dem Fenster spielen. Wenn Sie sich am Anfang der Lektion die Kurzübersicht zur Fensterklasse einmal angeschaut haben, so werden Sie dort u.a. die Methode PreCreateWindow(...) finden. Die Methode PreCreateWindow(...) wird durch den MFC-Rahmen aufgerufen bevor das WINDOWS Fenster erstellt wird. Durch Überschreiben der Methode und modifizieren der Elemente der übergebenen Struktur vom Typ CREATESTRUCT können einige Eigenschaften des neuen Fensters noch angepasst werden. Die übergebene Struktur wurde durch den MFC-Rahmen bereits initialisiert, so dass Sie 'nur' noch die Elemente anpassen müssen, die Sie auch verändern wollen.
Fügen Sie zunächst über den Klassen-Assistenten zur Hauptfensterklasse CMainWnd
die Methode PreCreateWindow(...) hinzu. Stellen Sie dann innerhalb dieser Methode
folgende Fensterparameter ein:
Wenn Sie sich nicht mehr sicher sind wie Sie den Fensterrahmen beeinflussen können, klicken Sie hier. Haben Sie den Fensterstil richtig gesetzt, so kann das Fenster nachher nicht mehr in seiner Größe durch Ziehen am Rahmen verändert werden.
|
Machen wir noch ein letztes 'Spielchen' mit unserem Fenster. In manchen Fällen kann es sinnvoll sein das Fenster zentriert auf dem Desktop anzuzeigen. Dazu muss aber zuerst die Größe des Desktop bekannt sein. Diese Daten liefert die API-Funktion GetSystemMetrics(...). Über den Parameter dieser Funktion können sie fast alle metrischen Daten des Systems abfragen.
Schreiben Sie nun die Methode PreCreateWindow(...) so um,
dass das Fenster zentriert auf dem Desktop erscheint. Zusätzlich soll das Fenster halb so
groß wie der Desktop werden.
|
Das fertige Beispiel finden Sie im Programmverzeichnis unter 03EPMMFC\MFCBasis.
So, in der nächsten Lektion werden wir uns ein vom Anwendungs-Assistenten erstellte Rahmenprogramm ansehen.
|
|
|
|
|
|