Windows Programmierung
| ||||||||||||
|
typedef struct tagMSG { HWND hwnd; // Handler des Nachrichtenempfängers UINT message; // Die Nachricht als Nummer WPARAM wParam; // 1. Parameter der Nachricht LPARAM lParam; // 2. Parameter der Nachricht DWORD time; // Zeitpunkt der Nachrichtenerzeugung POINT pt; // Cursorposition zum Zeitpunkt der Nachrichtenerzeugung } |
In der Variablen hwnd ist der Handler des Fensters gespeichert, an das die Nachricht gesendet wird. Ein Fenster kann jedoch seine Nachrichten nicht selbst verwalten. Diese Aufgabe kommt dem Thread zu, der das Fenster öffnet. Dazu kann der Thread über die Funktion GetMessage auf alle Nachrichten zugreifen, die an seine Fenster geschickt wurden. Nachrichten werden für gewöhnlich nicht als numerische Werte gesendet sondern über symbolische Konstanten, die alle in windows.h definiert sind. Beispiele für Nachrichten sind WM_KILLFOCUS (Fenster verliert Focus), WM_PAINT (Fenster neu zeichnen) und WM_LBUTTONUP (Linke Maustaste losgelassen).
|
#include <windows.h> int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE d2, LPSTR d3, int d4 ) {
HWND hwnd; // Handler für die Fensteradresse hwnd = CreateWindow( "BUTTON", "Hallo Welt!", WS_VISIBLE | BS_CENTER, 100, 100, 50, NULL, NULL, hInstance, NULL ); while ( GetMessage( &msg, NULL, 0, 0 ) ) {
{ DestroyWindow( hwnd ); // Fenster schließen PostQuitMessage(0); // Und Anwendung schließen } DispatchMessage(&msg); return msg.wParam; |
Funktionsweise:
Zunächst definieren wir die Funktion WinMain, die
die Einsprungadresse für Windows-Anwendungen darstellt. Mit
CreateWindow erzeugen wir ein Fenster, das wir
in diesem Fall so aussehen lassen wollen, wie es in der vordefinierten Klasse BUTTON
beschrieben ist.
Die Nachrichtenschleife besteht aus einer while-Schleife, die solange läuft, bis die Funktion
GetMessage den Wert FALSE zurückgibt. Dies ist der Fall, wenn
die Nachricht WM_QUIT in der Warteschlange liegt. Haben wir die Nachricht WM_LBUTTONUP erhalten (
die linke Maustaste wurde losgelassen), so "zerstören" wir zunächst unser Fenster
mit der Funktion DestroyWindow und senden dann
mit PostQuitMessage die Nachricht WM_QUIT.
Auf jeden Fall müssen wir über DispatchMessage
die Nachricht wieder ans System zurücksenden, damit die Windows-Standartnachrichtenhandler
sich um den Refresh des Fensters kümmern können. Was das bedeutet, sieht man, wenn man die
Anweisung aus dem Code weglässt.
Als nächstes wollen wir ein "echtes" (Windows-Typisches) Fenster erstellen. Dazu müssen wir zunächst eine eigene Fensterklasse ("WNDCLASS") erstellen. Die Struktur wird bereits vom System vorgegeben, wir brauchen nur noch die einzelnen Member mit Werten füllen:
|
typedef struct _WNDCLASS { UINT style; // Aussehen des Fensters mit CS_xxxxx WNDPROC lpfnWndProc; // Die Funktion zur Nachrichtenbehandlung, z.B. WndProc int cbClsExtra; // Zusätzlich zu reservierender Speicher (meist 0) int cbWndExtra; // Für das einbinden von Dialogen über WNDCLASS HANDLE hInstance; // Das Instanzenhandle der Applikation HICON hIcon; // Eine Icon-Resource für die Klasse HCURSOR hCursor; // Eine Cursor-Resource für die Klasse HBRUSH hbrBackground; // Pinsel für die Hintergrundfarbe LPCTSTR lpszMenuName; // Eine Resource für das Menü LPCTSTR lpszClassName; // Der Name, mit dem die Klasse registriert wird } WNDCLASS; |
Uns interessiert vor allem der Member lpfnWndProc. Hierbei handelt sich um einen "Pointer to a Funktion", also einen Zeiger auf eine Funktion. Diese Funktion muss unser Programm selbst definieren. Sie ist für das abarbeiten der Nachrichten zuständig, die unsere Applikation empfängt. Sehen wir uns ein einfaches Beispiel an, um zu verstehen, was es mit Fenstern auf sich hat. Die Funktion DrawText soll im wesentlichen unkommentiert bleiben. Auf das ausgeben von Grafik und Text wird in einem späteren Kapitel genauer eingegangen. Wir müssen nur wissen, das die Funktion sich zunächst beim System über den Zeichenbereich des Fensters informiert um dort dann zentriert einen Text auszugeben.
Unser Hauptprogramm registriert zunächst eine Fensterklasse und erstellt daraus ein Fenster. Dieses wird dann auch gleich angezeigt und die Daten aktuallisiert. Was folgt, ist die gewohnte Nachrichtenbehandlung, nur das wir die Nachrichten nichtmehr direkt sondern über WndProc abfangen. Wann immer das Fenster neu gezeichnet werden muss, schickt uns das System ein WM_PAINT, woraufhin wird unseren Text wieder abschicken. Nicht behandelte nachrichten schicken wir an den Standart-Handler DefWindowProc weiter.
Die C-Funktion memset hilft uns ein wenig weiter, um nicht alle Member der Klasse WNDCLASS setzen zu müssen. Wir definieren einfach, dass wir zunächst den gesamten Speicher, in dem das Objekt liegt, nullen wollen. Damit haben wir alle Member auf Standart NULL gesetzt und sparen uns eine Menge arbeit.
|
© Gerhard Zapf
|
||||
Letzte Änderung: 11.09.2003 |
||||