Programmieren unter MS-Windows

Kapitel 7: Das erste Windows-Programm

Letzte Änderung: 2.11.97 von B. Tritsch

Überblick

Zurück zum Index "PC- und MS-Windows-Support"

Zurück zum Inhalt


Man sagt manchmal, daß etwas nicht in Ordnung sein kann mit einem Betriebssystem, das sogar bei den einfachsten Programmen mehrere hundert Programmzeilen benötigt. Dabei wird immer mit dem berühmten "Hello World"-Programm unter UNIX verglichen. Diese Kapitel soll zeigen, daß die Legende der Riesenprogramme unter dem Monsterbetriebssystem Windows nicht unbedingt stimmen muß.

Hello World - der erste Versuch

Das einfachste aller Windows-Programme benötigt nur FÜNF Programmzeilen:

#include <windows.h>

int WINAPI WinMain(HINSTANCE d1, HINSTANCE d2, LPSTR d3, int d4)
 {
  MessageBox(NULL, ”Hello World”, ””, MB_OK);
 }

Dieses Programm zu kompilieren ist nicht schwieriger als dies bei dem Original "Hello World"-Programm der Fall ist. Voraussetzung ist, daß der Quellcode in der Datei "hello.c" abgespeichert wurde und alle Pfade für die Entwicklungsumgebung (Visual C++) gesetzt sind. Dann kann unter Windows NT oder Windows 95 folgende Zeile in der DOS-Box (Shell) eingegeben werden.

cl hello.c user32.lib

Danach kann das Programm HELLO.EXE gestartet werden. Es hat trotz seiner Einfachheit ein überraschend komplexes Verhalten im Bezug auf die Interaktionsmöglichkeiten mit dem Benutzer:

Dies ist ein bemerkenswertes Verhalten für einen Fünf-Zeiler. Das Geheimnis liegt in der Nachrichtenschleife (Message Loop) und der Fensterprozedur (Window Procedure). Diese werden in dem vorliegenden Fünf-Zeiler jedoch versteckt, so daß ein etwas komplexeres Programm erstellt werden muß, um hinter die Geheimnisse zum Verständnis von Windows zu kommen.

Hello World - der zweite Versuch

Das Problem des ersten "Hello World"-Programms ist seine Einfachheit. Die Funktion MessageBox versteckt einen Großteil der Funktionalität. Diese muß in der zweiten Version zumindest zum Teil sichtbar gemacht werden. Insbesondere gilt dies für die Nachrichtenschleife, die das Verhalten des resultierenden Fensters kontrolliert.

In der neuen Version des Programms erscheint der Text als Teil einer Schaltfläche, die die gesamte Client Area belegt. Zudem taucht er in der Titelzeile des Hauptfensters auf. Für die Realisierung des Programms wurden einige unorthodoxe Methoden angewendet, um es möglichst kurz zu halten.

Ein "normales" Windows-Programm registriert während seiner Initialisierungsphase eine neue Fensterklasse. Um dies zu verhindern, wurde für diese Beispiel die schon im System bestehende Klasse der BUTTON-Klasse. Diese beinhaltet auch schon die zugehörige Fensterprozedur und erleichtert dadurch die Übersichtlichkeit.

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE d2,
                   LPSTR d3, int d4)
 {
  MSG  msg;
  HWND hwnd;

  hwnd = CreateWindow("BUTTON", "Hello, World!",
                      WS_VISIBLE | BS_CENTER, 100, 100, 100, 80,
                      NULL, NULL, hInstance, NULL);
  while (GetMessage(&msg, NULL, 0, 0))
   {
    if (msg.message == WM_LBUTTONUP)
     {
      DestroyWindow(hwnd);
      PostQuitMessage(0);
     }
    DispatchMessage(&msg);
   }
  return msg.wParam;
 }

Dieses Beispiel zeigt nun zum ersten mal die geheimnisvolle Nachrichtenschleife. Nachdem das Fenster erzeugt wurde, läuft das Programm in eine while-Schleife, die wiederholt Aufrufe der GetMessage-Funktion durchführt. Immer, wenn die Applikation eine Nachricht erhält, returniert GetMessage. Der Return-Wert ist nur dann FALSE, wenn die erhaltene Nachricht WM_QUIT ist, was die Schleife beendet.

Der spezielle Fall der erhaltenen Nachricht WM_LEFTBUTTONUP wird behandelt. Der Aufruf von DestroyWindows veranlaßt die Zerstörung des Hauptfensters. Der Aufruf von PostQuitMessage stellt sicher, daß die GetMessage-Funktion die Nachricht WM_QUIT erhält, was die while-Schleife beendet.

Alle anderen Nachrichten an die Applikation werden "dispatched", aber an wen? Diese Nachrichten werden an eine Standard-Fensterprozedur der BUTTON-Klasse weitergeleitet, die für eine korrekte Behandlung sorgt. Dieser Mechanismus bleibt in diesem Beispiel jedoch verborgen. Erst ein umfangreicheres Beispiel kann mit Hilfe einer eigenen Fensterklasse und ihrer Fensterprozedur dieses Verhalten genauer erklären.

Zum nächsten Kapitel