3.1 Nachrichten (Meldungen, Messages)
Windows arbeitet meldungsbasiert, d.h. alle relevanten Ereignisse (z.B.: Maus-Klick, Tastendruck, Ablauf eines Zeit - Intervalls...) erzeugen Meldungen, die danach in sogenannten Nachrichten - Schleifen verarbeitet werden.
Nachrichten - Charakteristik:
. werden in Form einer vorzeichenlosen 16-Bit Ganzzahl gespeichert
. werden durch vordefinierte Konstanten (in WINDOWS.H, ca. 250) dargestellt
o WM_LBUTTONDOWN Linke Maustaste gedrückt
o WM_CLOSE Anwendung wird geschlossen
o WM_KEYDOWN Taste gedrückt
o WM_RESIZE Fenstergröße wird geändert
. können mittels \"WinSight\" protokolliert werden
Jede Meldung liefert zusätzliche Informationen (z.B.: WM_KEYDOWN liefert zusätzlich: welche Taste gedrückt? Welche Zusatztasten (Alt, Strg, ...) gedrückt?). Diese Informationen werden in zwei Parametern geliefert, die Bedeutung dieser Parameter ist meldungsabhängig.
. WPARAM ... Parameter vom Typ WORD
. LPARAM ... Parameter vom Typ LONG
Windows verwendet 2 verschiedene Übergabe - Mechanismen:
PUSH - Modell:
Übergabe erfolgt bei GetMessage, die Applikation ist aktiv. Die Meldung wird in einer MSG - Struktur übergeben.
PULL - Modell:
Aufruf einer Fensterfunktion durch Windows, die Applikation ist passiv. Die Meldung wird in Form einzelner Parameter übergeben.
3.2 Nachrichten-Konzept von Windows
Die Folgende Grafik zeigt den Meldungsfluß zwischen Windows und den Einzelnen Applikationen.
3.3 WinMain
Die Funktion WinMain entspricht der Funktion main() in einen normalen C-Programm, sie wird von Windows beim Programmstart aufgerufen.
Fix vorgegebener Funktions-Kopf:
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow);
(1) (2) (3) (4) (5) (6)
(1)
(2)
(3)
(4)
(5)
(6) liefert im Fehlerfall einen Wert ungleich 0
Windows-\"Aufruf-Konvention\", spart Code (da nur eine fixe Anzahl von Parametern erlaubt werden, der Stack wird abgebaut)
Bezug auf die aktuelle Programm-Instanz (siehe 2.3 Instanzen)
Bezug der vorhergehenden Programm - Instanz
Kommandozeilenparameter (entspricht argv in Standard-C)
Pramater für die Funktion ShowWindow, gibt an, wie das Fenster dargestellt werden soll (Vollbild, Fenster, Symbol)
Die Funktion WinMain erfüllt eine Reihe von wichtigen Routine-Aufgaben:
Registrieren der Hauptfenster-Klasse
Wird das Programm zum ersten Mal aufgerufen, wird eine Fensterklasse erzeugt, dieser Vorgang ist bei weiteen Programminstanzen nicht mehr notwendig. (siehe 2.3 Instanzen)
Im zuge der Registration werden einige Fenster - Eigenschaften festgelegt. Jedes Windows - Fenster muß einer registrierten Klasse angehören, deshalb gibt es einige vorregistrierte Klassen für Standard-Fenster wie etwa MessageBox, Button, ListBox, ...
Erzeugen des Hauptfensters
Ist eine entsprechende Klasse registriert, wird das Hauptfenster erzeugt. Dieser Vorgang ist bei jeder Programm - Instanz notwendig, er legt die restlichen Fenstereigenschaften fest (z.B.: Fensterstil)
Anzeigen des Hauptfensters
Durch Aufruf der Funktion ShowWindow (die den Parameter nShow übernimmt) und einem anschließendem UpdateWindow wird das Fenster angezeigt.
Initialisieren der Meldungsschleife
Die Funktion GetMessage liefert anliegende Nachrichten aus der Meldungsschleife.
3.4 Die Fensterfunktion
Die Fensterfunktion wird von Windows aufgerufen (PUSH - Modell), sie ist für die Meldungsauswertung zuständig.
Fix vorgegebener Funktions-Kopf:
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP);
HWND hWnd
UINT msg
WPARAM wP
LPARAM lP Fenster-Bezug
Meldungscode (z.B.: WM_PAINT, WM_CLOSE, ...)
Zusatz-Parameter vom Typ WORD (16 Bit)
Zusatz-Parameter vom Typ LONG (32 Bit)
Die Fensterfunktion sollte nicht alle Meldungen selbst behandeln, sondern nur einige, wichtige. Andere Meldungsbearbeitungsfunktionen (ein wahres Unwort) können deshalb ausgelagert werden, oder, wenn keine spezielle Behandlung erwünscht ist, an die Default-Fensterfunktion DefWindowProc weitergeleitet werden.
Beispiel für ausgelagerte Meldungsbearbeitung:
...
void WndProcWMCOMMAND(HWND hWnd, WPARAM wParam)
{
// Abarbeitung der Meldungen für Menü, Toolbar, ...
...
}
void WndProcWMPAINT(HWND hWnd, WPARAM wParam)
{
// Bildschirmausgabe
...
}
LONG WndProcWMCLOSE (HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
// Rückfrage, evt. Einstellungen oder Arbeitsbereich speichern
...
}
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
LONG ret = 0;
...
switch (msg)
{
case WM_COMMAND: WndProcWMCOMMAND(hWnd,wP); break;
case WM_PAINT: WndProcWMPAINT(hWnd,wP); break;
case WM_CLOSE: ret = WndProcWMCLOSE(hWnd, msg, wP, lP); break;
case WM_DESTROY: PostQuitMessage (0); break;
default: ret = DefWindowProc(hWnd msg, wP, lP);
}
return ret;
}
3.5 Abhandlung bei \"Anwendung beenden\"
Anhand des Beispiels \"Anwendung beenden\" soll gezeigt werden, wie das Programm auf die Benutzeraufforderung reagiert, sich zu beenden.
(2)
(4)
(1)
(3)
(5) ...
void WndProcWMCOMMAND(HWND hWnd, WPARAM wParam)
{
...
switch (wParam)
{
case MENU_ENDE: PostMessage (hWnd,WM_CLOSE,0,0); break;
...
}
...
}
LONG WndProcWMCLOSE (HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
if(MessageBox(\"Wirklich beenden?\",\"Beenden\",MB_YESNO) == IDYES)
return DefWindowProc (hWnd, msg, w, lP);
else return 0;
}
LONG FAR PASCAL _export WndProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP)
{
LONG ret = 0;
...
switch (msg)
{
case WM_COMMAND: WndProcWMCOMMAND(hWnd,wP); break;
case WM_CLOSE: ret = WndProcWMCLOSE(hWnd, msg, wP, lP); break;
case WM_DESTROY: PostQuitMessage (0); break;
default: ret = DefWindowProc(hWnd msg, wP, lP);
}
return ret;
}
Erläuterung:
1. Der Aufruf des Menüpunktes \"Datei/Beenden\" löst ein WM_COMMAND aus, dieses wird zur Bearbeitung an die Funktion WndProcWMCOMMAND übergeben.
2. In der Funktion WndProcWMCOMMAND wird der in wPararm übergebene ID-Wert ausgewertet, bei MENU_ENDE wird mittels PostMessage (siehe 3.6) die Nachricht WM_CLOSE an das Programmfenster geschickt.
3. Das Programmfenster reagiert auf WM_CLOSE mit dem Aufruf der Prozedur WndProcWMCLOSE.
4. Die Funktion WndProcWMCLOSE leitet die Meldung nach Rückfrage an den User an die Default-Window-Funktin DefWindowProc weiter, diese löst die Nachricht WM_DESTROY aus.
5. WM_DESTROY wird von der Fensterfunktion mit dem Aufruf von PostQuitMessage beantwortet, die Anwendung wird geschlossen.
3.6 Nachrichten versenden
Jede Windows - Applikation kann Nachrichten an beliebige Fenster verschicken. Man unterscheidet nach dem Verhalten nachdem die Nachricht verschickt wurde, zwei Übermittlungsmethoden:
Synchrone Übertragung:
. mittels SendMessage (hWnd, msg, wParam, lParam);
. Die Applikation, die die Nachricht verschickt hat wartet, bis das Zielfenster die Nachricht bearbeitet hat. Der Rücksprung aus der Funktion SendMessage erfolgt erst nach der Abarbeitung.
Asynchrone Übertragung:
. mittels PostMessage (hWnd, msg, wParam, lParam);
. Der Rücksprung aus der Funktion PostMessage erfolgt sofort, die Applikation läuft weiter. Die Nachricht wird in die Nachrichten - Warteschlange der Zielapplikation gestellt.
|