In dem ersten Tutorial zeige ich dir, wie man eine ganz einfache Ausgabe in Form eines
Nachrichtenfensters macht. Hierfür benutzen wir die MessageBox
Funktion,
die genau dafür konzipiert wurde.
Zu aller erst musst du ein neues Projekt (wichtig: Windows Anwendung bzw.
-tW
Compiler Flag beim Borland C++ Compiler) erstellen
(Anleitung für Visual C++ 6).
Damit wir von einer verbesserten Typsicherheit profitieren, müssen wir vor dem Einbinden
der Windows Headerdatei einen Bezeichner definieren.
#define STRICT
Dann muss die haupt Windows API Headerdatei eingebunden werden. In diese Datei werden wiederum andere Dateien eingebunden, sodass man schließlich alle Prototypen und Konstanten deklariert hat. Diese Zeile muss in jedem Programm, dass Teile der Windows API benutzt, vorhanden sein.
#include <windows.h>
Die nächste Anweisung speichert unseren Witz, der nachher ausgegeben werden soll, unter
dem Namen szWitz
als konstante Zeichenkette ab.
const char szWitz[] = "\"Ich steh' schwer auf Umweltschutz\", sagt Peter.\n" "\"Ich werfe zum Beispiel alte U-Bahn-Fahrscheine nie weg,\n" "sondern benutze sie mehrmals.\"";
In jedem Programm braucht man eine Funktion, die als Einstiegspunkt dient. Diese Funktion
wird praktisch vom Betriebssystem aufgerufen und bekommt meistens Daten als Parameter
überliefert. Wenn die Hauptfunktion beendet ist, dann ist auch das Programm beendet.
In Dos war dies die main
Funktion. Da man Windows und Dos Programme klar
von einander trennen wollte, heißt die Hauptfunktion in Windows WinMain
.
Rückgabetyp ist wie auch in Dos Zeiten ein int
Wert. WINAPI
steht vor allen Windows API Funktionen und legt die Aufrufkonvention fest. In MS Visual
C++ 6 steht WINAPI
für __stdcall
. Das bedeutet, dass die
Parameter von Rechts nach Links übergeben werden, dass die Werte per Value
übergeben werden, also eine Kopie erzeugt wird, und einiges mehr (im MSND: The __stdcall
Keyword). Die Parameter der WinMain
Funktion erkläre ich dir im nächsten Tutorial, da wir die Parameter in diesem
Tutorial noch nicht benötigen.
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
Dir ist sicher aufgefallen, dass alle Variablennamen mit einem Präfix beginnen. Man
schreibt vor eine Variable vom Typ int
ein i, damit man später noch
weiß, welchen Typ diese Variable hat. Diese Art der Namensgebung nennt man
'ungarische Notation' zu Ehren des Microsoft Programmierers Charles Simonyi,
der Ungarischer Staatsbürger ist. Ich habe eine Liste aller Präfixe zusammengestellt.
Die MessageBox
Funktion (im MSDN: MessageBox
) gibt in einem separaten Fenster eine Nachricht aus. Der
erste Parameter soll normalerweise ein Handle auf ein Fenster sein, zu dem die Nachricht
gehören soll (und das die Funktion solange lahm legen soll), aber da wir kein
Fenster besitzen, geben wir Null an. Dies bedeutet, dass
die Nachricht als eigenständiges Fenster dargestellt wird. Was ein Handle ist und wie
man ein Fenster erzeugt, lernst du im zweiten Tutorial. Der zweite Parameter ist ein Zeiger
auf eine C-Zeichenkette, die als Text im Nachrichtenfenster ausgegeben werden soll. Der
dritte Parameter ist auch ein Zeiger auf eine Zeichenkette. Dieser Text wird in der Titelleiste
des Fensters angezeigt. Mit dem vierten Parameter kann man das äußerliche
Erscheinungsbild der
Nachricht beeinflussen. So bekommt ein Nachrichtenfenster ein bestimmtes Icon und die Art
und Anzahl der Buttons wird festgelegt. In unserem Fall bekommt das Fenster ein
"Information" Icon und die Buttons "Ok" und "Abbrechen" von
denen der erste der standard Button ist. Im Rückgabewert wird gespeichert, welcher
Button nun gedrückt wurde. Diese Information speichern wir in der Variablen
iAntwort
.
int iAntwort = MessageBox(NULL, szWitz, "Ha, ha, ha, ha...", MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON1);
In der nächsten Anweisung prüfen wir, ob der Benutzer in dem vorherigen
Nachrichtenfenster auf "Ok" gedrückt hat. Wenn dies der Fall war, dann
geben wir noch eine Nachricht aus, in der genau dies steht. Wir geben wieder
MB_ICONINFORMATION
an, aber diesmal MB_OK
. Die Konstante
MB_DEFBUTTON1
behalten wir bei.
if (IDOK == iAntwort) { MessageBox(NULL, "Ja, ich finde den Witz auch Ok...", "Sie haben auf Ok gedrückt", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1); }
Wenn der Benutzer jedoch den "Abbrechen" Button gedrückt hat, geben wir
eine andere Nachricht aus. Wir können hier nicht einfach else
statt
else if
schreiben, da die MessageBox
Funktion bei einem
Fehler Null zurückgibt und wir dann den Fehler als Abbrechen interpretieren
würden.
else if (IDCANCEL == iAntwort) { MessageBox(NULL, "Ja, warum haben sie denn auf Abbrechen gedrückt?\n" "Hat ihnen der Witz etwa nicht gefallen?", "Sie haben auf Abbrechen gedrückt", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1); }
Da die WinMain
Funktion einen Rückgabetyp angegeben hat, müssen
wir nun auch einen zurückgeben. Man darf die WinMain
Deklaration
natürlich nicht ändern, so darf man in ISO-C auch kein void
als Rückgabetyp der Hauptfunktion angeben. Null als Rückgabewert steht für
erfolgreich beendet und alles ungleich Null deutet auf einen Fehler hin.
return 0; }
Dies musst du dann noch mit einem Windows fähigen Compiler compilieren (Anleitung für Visual C++ 6). Nach dem Ausführen des Programms müsste das erste Nachrichtenfenster erscheinen.
Wer eine IDE benutzt, die Eingabehilfen anbietet (wie Visual C++ 6), wird
merken, dass ich ein paar Variablen und Typen anders geschrieben habe, als dort vielleicht
angegeben. Dies ist unter Umständen im dritten Parameter der WinMain
Funktion
der Fall. Dort schreibe ich PSTR szCmdLine
und andere werden vielleicht
LPSTR lpCmdLine
schreiben. Der Typ LPSTR
bedeutet "Long Pointer
to a String" und ist veraltet, da es in Windows 32 Systemen keine Long (far) Pointer
mehr gibt. Der Präfix sz
("String terminated by Zero") beschreibt
den Typ viel besser, als lp
("Long Pointer"). Für den Compiler
sind natürlich beide Varianten identisch, da der Unterschied durch den Präprozessor
eleminiert wird. Und da wir gerade bei der Namensgebung sind: MB_*
steht für
MessageBox
. Dies findet man in der Windows API häufig, dass die Konstanten
im Zusammenhang mit einer Funktion ein Kürzel des Funktionsnamen als Präfix
tragen.
MessageBox
Funktion.