Aufbau einer Windowsanwendung

Die Methode WinMain(...)

Generell funktioniert eine Windows-Anwendung wie folgt: Nach dem der Benutzer eine Anwendung startet ruft Windows eine von der Anwendung bereitgestellte Funktion namens 'WinMain(...)' auf. Die Deklaration dieser Funktion sieht im allgemeinen wie folgt aus:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

Die Datentypen:

Datentyp Erläuterung
HINSTANCE - Handle auf Anwendungsinstanz
- ermöglicht dem System die eindeutige Zuordnung einer gestarteten Anwendung
LPSTR - eine Zeichenkette (entspricht: char*)

Die Parameter:

Parameter Erläuterung
hInstance - Instanz der gestarteten Anwendung
hPrevInstance - bedeutungslos ab WIN32 (immer NULL) *
lpCmdLine - Kommandozeile (beim Start übergebene Parameter)
nCmdShow - legt fest wie die Anwendung gestartet wird (maximiert, minimiert etc.)

*wurde bei einem 16-Bit Windows eine Anwendung mehrfach gestartet wurde dem Parameter 'hPrevInstance' der Wert der zuletzt geöffneten Anwendungsinstanz zugewiesen.

Innerhalb der Methode 'WinMain(...)' wird das Hauptfenster erstellt und angezeigt und eine sogenannte Nachrichtenschleife erstellt.

Das Nachrichtenkonzept und die Nachrichtenschleife

Windows fängt jede Aktion des Benutzers in Form einer Nachricht ab. Drückt der Benutzer innerhalb eines Fensters eine Taste, bewegt er die Maus, klickt er einen Befehl an, so sendet Windows die entsprechende Nachricht an eine Nachrichtenwarteschlange. Aufgabe des Programms ist nun diese Nachrichten aus der Warteschlange abzurufen und entsprechend zu verarbeiten. Dies wird innerhalb eines Programms  mithilfe der sogenannten Nachrichtenschleife erreicht, welche sich von Anwendung zu Anwendung praktisch nicht unterscheidet. In ihrer einfachsten Form sieht sie in etwa wie folgt aus:

while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

Die Funktion 'GetMessage(...)' ermittelt die Nachricht aus der Nachrichtenschleife und speichert deren Informationen innerhalb einer Struktur vom Typ 'MSG'. (Die genaue Definition dieser Struktur interessiert hier nicht weiter). Der erste Parameter stellt eine Instanz der zuvor genannten Struktur dar. Der zweite entspricht einem Handle auf das gewünschte Fenster. Dieser Parameter wird meist auf 'NULL' gesetzt um alle Fenster einer Anwendung zu erfassen. Die nächsten Parameter ermöglichen es die Nachrichten, welche abgefangen werden näher einzugrenzen. Ist dies nicht gewünscht, so werden beide auf '0' gesetzt. Die Funktion besitzt den Rückgabetyp 'BOOL'. Die Funktion gibt also entweder 'TRUE' oder 'FALSE' zurück.

Die Funktion 'TranslateMessage(...)' ist ausschließlich für Tastaturnachrichten vorgesehen. Jede Tastatureingabe (bestehend aus Drücken und dem  Lösen einer Taste) wird, sofern möglich, als  Texteingabe interpretiert. Diese Methode erzeugt dann eine neue Nachricht welche dem Programm den Druck einer Zeichentaste ankündigt. So wird '<shift> + <v>' als 'V' interpretiert. Die Nachrichten die durch das Drücken und das Lösen der Taste ausgelöst werden, werden allerdings auch weitergesendet.

Die Funktion 'DispatchMessage(...)' verteilt die Nachrichten mithilfe von Fensterprozeduren dann an die entsprechenden Fenster. (Dieser Vorgang wird im nächsten Abschnitt erläutert)

Die Nachrichtenschleife endet dann, wenn die Methode 'GetMessage(...)' den Wert 'FALSE' zurückliefert. Dies wiederum geschieht genau dann, wenn das Programm eine Nachricht erhält, die es zum Beenden auffordert. Nach Ende der Nachrichtenschleife sollte das Programm dann auch tatsächlich (nach eventuellen Aufräumarbeiten) mit einer 'return'-Anweisung beendet werden.

Die Fensterprozedur

Jedem Fenster wird bei seiner Erstellung eine sogenannte Fensterprozedur zugewiesen. Der Funktionsname kann dabei vom Benutzer frei gewählt werden. Diese Fensterprozedur ist für die Verarbeitung aller an das entsprechende Fenster zugesandten Nachrichten verantwortlich. Die Fensterprozedur setzt dort ein wo die Nachrichtenschleife mit der Funktion 'DispatchMessage(...)' aufgehört hat. So kommen bei dieser Prozedur die Nachrichten in Form von Konstanten, das entsprechende Fensterhandle (Datentyp: 'HWND') und zwei für die jeweiligen Nachrichten spezifische Zusatzparameter an.  Die Fensterprozedur wird nicht vom Programmierer sondern von Windows aufgerufen. Ihre allgemeine Deklaration sieht wie folgt aus:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);

Die Datentypen:

Datentyp Erläuterung
LRESULT - ganzzahliger 32-Bit Rückgabewert (normalerweise 0)
HWND - Fensterhandle
UINT - entsprich unsigned int
WPARAM - Datentyp für Parameter (entspricht einem 32-Bit-Integer)*
LPARAM - Datentyp für Parameter (entspricht einem 32-Bit-Integer)

*das 'W' für 'WORD' (unsigned short) entspricht noch der 16-Bit-Zeit. Mittlerweile handelt es sich hierbei um einen 32-Bit-Integer

Die Parameter:

Parameter Erläuterung
hWnd - Fensterhandle des entsprechenden Fensters
uiMessage - Nachrichtenkonstante in der Form WM_x (WM: Window Message)
wParam - 1. Parameter
lParam - 2. Parameter

Jede von Windows gesendete Nachricht besitzt eine Standardbehandlung. Möchten Sie die Behandlung solcher Nachrichten Windows überlassen rufen Sie einfach die Methode 'DefWindowProc(...)' auf. Die Deklaration entspricht der von 'WndProc(...)', muss also nicht noch einmal erläutert werden.

Zusammenfassung

Hier wurde kurz der Aufbau einer Windowsanwendung dargestellt. Um die gegenseitigen Aufrufe noch einmal zu veranschaulichen, habe ich folgende Skizze entworfen. Sie stellt die Funktionsaufrufe zwischen Windows und Anwendung dar:

Die nächsten Lektionen

In der nächsten Lektion möchte ich vor allem auf die Erstellung eines Fensters eingehen und die damit verbundenen Aufgaben erläutern.

Nach oben Weiter