Fensterklasse

Zurück Zum Inhaltsverzeichnis Weiter

Hier zur Erinnerung nochmals die fünf Schritte für die Erstellung eines Fensters:

no1.gif (995 Byte) Festlegen der generellen Eigenschaften eines Fensters über die Fensterklasse.
Festlegen der individuellen Eigenschaften eines Fensters und Erstellung des Fensters.
Anzeigen des Fensters.
Schreiben der Nachrichtenschleife um die Nachrichten abzuholen und zu verteilen.
Schreiben des Programmteiles zur Verarbeitung der Nachrichten. Dieser Programmteil wird auch als Fensterprozedur bezeichnet.

Fangen wir mit dem ersten Punkt Festlegen der generellen Fenstereigenschaften an. Die generellen Eigenschaften eines oder mehrere Fenster werden durch die sogenannte Fensterklasse bestimmt. Um eine Fensterklasse zu erstellen wird die Funktion RegisterClassEx(...) aufgerufen. Diese Funktion erhält als Parameter einen Zeiger auf eine Struktur vom Typ WNDCLASSEX, die folgenden Aufbau besitzt:

typedef struct _WNDCLASSEX
{
    UINT     cbSize;
    UINT     style;
    WNDPROC  lpfnWndProc;
    int      cbClsExtra;
    int      cbWndExtra;
    HANDLE   hInstance;
    HICON    hIcon;
    HCURSOR  hCursor;
    HBRUSH   hbrBackground;
    LPCTSTR  lpszMenuName;
    LPCTSTR  lpszClassName;
    HICON    hIconSm;
} WNDCLASSEX;

Über diese Struktur werden die generellen Eigenschaften eines Fenster festgelegt. Sehen wir uns wegen der Wichtigkeit der Struktur ihre Elemente kurz an.

Das Strukturelement cbSize gibt die Größe der Struktur in Bytes an und sollte immer wie folgt gesetzt werden:

strMyWndCls.cbSize = sizeof(WNDCLASSEX).

Danach folgt der Fensterklassenstil style. Er kann unter anderem eine Kombination aus folgenden Werten sein:

Stil

Bedeutung

CS_DBLCLKS Erlaubt der Fensterklasse das Versenden von Doppelklick-Nachrichten wenn der Anwender mit der Maus innerhalb eines Fensters, das zur Fensterklasse, gehört einen Doppelklick ausführt.
Standardmäßig werden keine Doppelklick-Nachrichten versandt!
CS_HREDRAW Veranlasst das Neuzeichnen des gesamten Fensters wenn die Breite der Client-Area verändert wurde.
CS_VREDRAW Veranlasst das Neuzeichnen des gesamten Fensters wenn die Höhe der Client-Area verändert wurde.
CS_NOCLOSE Sperrt den 'Schließen-Befehl' im System-Menü des Fensters. Zusätzlich wird das Schließ-Symbol Image1.gif (888 Byte) gesperrt.

Für eine vollständige Aufzählung aller möglichen Fensterstile sehen Sie bitte unter dem Stichwort WNDCLASSEX in der Online-Hilfe zum Compiler nach.

Als nächstes Element folgt der Funktionszeiger lpfnWndProc. Er zeigt auf die zur Fensterklasse gehörige Fensterprozedur. Alle Fenster die zu ein und der selben Fensterklasse gehören, besitzen eine gemeinsame Fensterprozedur! Und innerhalb dieser Fensterprozedur werden (im Regelfall) alle Nachrichten an die Fenster verarbeitet. Sie erinnern sich doch noch: Nachrichten sind in der Regel immer an Fenster gerichtet! Die Fensterprozedur wird später noch genau betrachtet.

Die beiden nächsten Parameter cbClsExtra und cbWndExtra dienen zum Reservieren von zusätzlichen Bytes zur Fensterklasse bzw. zum jeweiligen Fensters. Diese Einträge werden im Kurs nicht näher betrachtet, da Fenster unter C++ als Objekte definiert werden und ihre Daten innerhalb der C++ Klasse ablegen.

Als nächstes folgt hInstance. Dies ist das Handle auf die Instanz, in der sich die Fensterprozedur befindet. Im Regelfall wird hier der Wert eingesetzt, den die Funktion WinMain(...) als Parameter erhält.

hIcon und hCursor  sind Icon- bzw. Cursor-Handle. Das über hIcon spezifizierte Icon wird angezeigt wenn das Fenster als großes Symbol dargestellt wird (z.B. im Explorer). Um ein Handle für ein Icon zu erhalten müssen Sie das entsprechende Symbol zuerst laden. Dies erfolgt mit der Funktion LoadIcon(...). Als Parameter erhält die Funktion unter anderem den Namen des zu ladenden Icon und liefert dann als Returnwert das erforderliche Handle darauf zurück.  Fast genau gleich verhält es sich mit dem Cursor-Handle.  Auch der zu verwendende Cursor muss zuerst mittels LoadCursor(...) geladen werden . Diese Funktion erhält jetzt als Parameter unter anderem den Namen des zu ladenden Cursor und liefert als Returnwert das Handle des Cursors zurück. Über dieses Cursor-Handle ist damit der Cursor spezifiziert, der dargestellt wird wenn sich der Mauszeiger innerhalb der Client-Area des Fensters befindet. Was es mit dem Begriff Client-Area auf sich hat erfahren Sie später noch.

Ebenfalls ein Handle ist das Element hbrBackground. Über dieses Handle wird festgelegt, mit welchem Brush (Pinsel) der Hintergrund des Fensters (bzw. alle Fenster die zur Fensterklasse gehören) ausgefüllt wird. Im Prinzip ist ein Brush eine kleine Bitmap die zum Ausfüllen von verschiedenen Flächen verwendet wird. Da wir aber im Augenblick noch keine Bitmaps laden bzw. erzeugen können, verwenden wir für den Fensterhintergrund einen vom System vorgegebene Brush. Um einen solchen Brush zu laden ist die Funktion GetStockObject(...) aufzurufen. Über den Parameter der Funktion wird der zu ladende Brush bestimmt. Als Returnwert erhalten Sie ein Handle auf ein allgemeines GDI-Objekt (GDI = graphic device interface). Dieses Handle muss über eine Typkonvertierung in den erforderlichen Datentyp HBRUSH konvertiert werden (sonst erhalten Sie beim Übersetzen des Programms eine Fehlermeldung!).

Außer durch einen Brush lässt sich der Fensterhintergrund auch auf eine über die Systemsteuerung eingestellte Systemfarbe setzen. Dazu stehen eine ganze Reihe von Konstanten wie z.B. COLOR_BACKGROUND oder COLOR_WINDOWTEXT zur Verfügung. Um den Fensterhintergrund auf eine dieser Farben zu setzen wird folgende Anweisung verwendet:

strMyWndCls.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);

Beachten Sie hier bitte, dass zur Farbkonstante der Wert '1' dazuaddiert werden muss. Eine Aufstellung aller möglichen Farbkonstanten erhalten Sie in der Online-Hilfe ebenfalls unter dem Stichwort WNDCLASSEX.

lpszMenuName ist ein Zeiger auf das Standard-Menü der Fensterklasse. Dieses Menü muss in der Ressource (wird später ausführlich erläutert) des Programms enthalten sein. Soll kein Standard-Menü zugeordnet werden, und das ist der Regelfall den Fenster besitzen normalerweise ein individuelles Menü, wird der Wert 'NULL' angegeben.

Das Element lpszClassName ist schließlich der Zeiger auf den Namen der Fensterklasse. Dieser Name ist als String anzugeben (mit '0' abgeschlossene Zeichenkette) und muss im gesamten System eindeutig sein. Über diesen Namen erfolgt später die Zuordnung eines Fensters zu einer Fensterklasse.

Der letzte Parameter hIconSm ist ein weiteres Handle auf ein Icon. Dieses (kleine) Symbol wird zum einen in der Titelzeile des Fensters links oben dargestellt und zum anderen wenn das Fenster zum Symbol verkleinert wird.

Damit ist die Erstellung einer Fensterklasse abgeschlossen.

Bauen wir nun das Beispiel für dieses Kapitel langsam auf. In den nachfolgenden Lektionen wird dann das Beispiel ständig erweitert bis wir am Schluss ein 'richtig funktionierendes' Fenster erstellt haben.

Versuchen Sie nun aber zunächst einmal eine Fensterklasse für ein Fenster mit folgenden Eigenschaften zu erstellen:

  • Als Icon soll das WINDOWS Logo verwendet werden
  • Als Cursor soll ein Pfeil nach oben darstellt werden.
  • Der Fensterhintergrund soll hellgrau dargestellt werden.
  • Für die Fensterprozedur ist eine Funktion namens WndProc einzusetzen.

Die Fensterprozedur WndProc wird erst später noch definiert. Geben Sie beim Ausfüllen der WNDCLASSEX Struktur beim entsprechenden Element lediglich WndProc an.

Erstellen Sie sich jetzt eine neue Win32-Anwendung mit Hilfe des Assistenten, so wie in der Lektion Messageboxen beschrieben. Geben Sie dem Projekt den Namen FirstWin.

Nachdem Sie die Erstellung der Fensterklasse eingegeben haben, übersetzen Sie das Beispiel um mögliche Fehler aufzuspüren. Den einzigen Fehler den Sie im Beispiel noch nicht beseitigen können ist die fehlende Definition der Fensterprozedur WndProc. Die kommt erst später.

Lösung zur Definition einer Fensterklasse

Erinnern Sie sich noch an den Anfang des Kurses? Dort wurde erklärt wie Listings zu interpretieren sind. Die kursiven, schwarzen Anweisungen wurden entweder durch den Assistenten erstellt oder in einem früheren Schritt schon eingegeben. Wenn Sie sich den Code aus dem Listing in Ihr Projekt kopieren wollen, kopieren Sie also nur die nicht-kursiven blauen und braunen Anweisungen. Aber kopieren Sie alle notwendigen Teile!
// FirstWin.cpp : Definiert den Einsprungpunkt für die Anwendung.
//

#include "stdafx.h"

// Konstanten
// ----------
// Fensterklassen-Name
LPCTSTR lpszWCLASSNAME = "ERSTES FENSTER";

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow )
{
    // ZU ERLEDIGEN: Fügen Sie hier den Code ein.


    // Fensterklasse registrieren
    // --------------------------
    // WNDCLASS-Strukur
    WNDCLASSEX WndClass;
    // Struktur mit '0' vorbelegen
    memset(&WndClass,0,sizeof(WndClass));
    WndClass.cbSize = sizeof(WndClass);
    // Fensterprozedur einhaengen
    WndClass.lpfnWndProc = WndProc;
    // Instanzen-Handle
    WndClass.hInstance = hInstance;
    // Icon fuer Fensterklasse laden
    WndClass.hIcon = LoadIcon(0,IDI_WINLOGO);
    // Cursor fuer Fensterklasse laden
    WndClass.hCursor = LoadCursor(0,IDC_UPARROW);
    // Fensterhintergrund setzen
    WndClass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
    // Fensterklassen-Name
    WndClass.lpszClassName = lpszWCLASSNAME;
    // Fensterklasse registrieren
    RegisterClassEx(&WndClass);

    return 0;
}

Ganz am Anfang des Listings wird der Name der Fensterklasse festgelegt. Dies erfolgt über die Definition der Konstanten lpszWCLASSNAME vom Typ LPCTSTR.

Als nächstes wird die Struktur WNDCLASSEX definiert und mit '0' initialisiert. Durch diese Vorbelegung mit dem Wert 0 wird allen Strukturelementen ihr Defaultwert zugewiesen. Danach wird die Größe der Struktur im Element cbSize und der Zeiger auf die Fensterprozedur in lpfnWndProc eingetragen. Für das Instanzen-Handle hInstance wird der an WinMain(...) als Parameter übergebene Wert übernommen. Die Fensterklasse erhält als Icon das System-Icon 'IDI_WINLOGO' und als Cursor den System-Cursor 'IDC_UPARROW'. Wenn Sie sich nicht mehr sicher sind, welche Werte Sie hier einsetzen können, klicken Sie für die Icon-Werte hier und für die Cursor-Werte hier. Anschließend wird der Hintergrund der Fensterklasse festgelegt. Dies erfolgt durch Laden des System-Brush 'LTGRAY_BRUSH'. Für den Namen der Fensterklasse wird die am Anfang definierte Konstante lpszWCLASSNAME eingesetzt.

Ende der Lösung

Ansonsten geht's jetzt anschließend weiter mit dem Festlegen der individuellen Eigenschaften eines Fensters.

Zurück Zum Inhaltsverzeichnis Weiter


Copyright © 2004

Senden Sie Emails mit Fragen oder Kommentaren zu dieser Website an: mailto:info@cpp-tutor.de
 Wolfgang Schröder, Lerchenweg 23, D-72805 Lichtenstein. Tel: +49 7129 6470