______________________________________________________________________
// 2_2 Ein Windows Fenster
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// Nachrichten von Windows an unser Programm werden in dieser Funktion
// verarbeitet
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam,
LPARAM lparam) /* der Name ist frei wählbar,
meist wird aber WindowProc
benutzt. Die Rückgabe geht
an Windows zurück und die
Paramter werden von Windows
übergeben, da Windows so frech
ist, einfach selbstständig
diese Funktion aufzurufen.
Daher interessieren uns also
weder Rückgabetyp noch
Parameter, bis auf Parameter 2.
Dieser enthält immerhin die zu
verarbeitende Windows-Nachricht
an unser Programm.*/
{
HDC hdc;
RECT rect;
const char text[] = "Hallo Welt";
switch(message)
{
case WM_MOVE: /* wird das Fenster bewegt, so soll der Text neu gezeichnet
werden (Auch das Erzeugen des Fensters zum Programmstart
zählt als Bewegung des Fensters):*/
{
hdc = GetDC(hwnd); // ein Gerätekontext wird erzeugt.
// Gerätekontexte besprechen wir später.
GetClientRect(hwnd, &rect); /* Der Arbeitbereich des Fensters
( Der Bereich, der nicht von
Rahmen, Titel-, Menü- und Symbol-
leiste beansprucht wird) wird
abgemessen.
Parameter 1 benötigt mal wieder
ein Handle auf das Fenster,
welches die Funktion bearbeiten
soll. Als 2. Parameter wird noch
eine Adresse benötigt, an der
die Grösse des Arbeitbereichs
gespeichert wird.*/
TextOut(hdc, rect.right/2 - 40, rect.bottom/2 - 10,
text, strlen(text)); /* so der ganze Aufwand für das
Fenster und jetzt sorgt diese
Funktion ganz alleine dafür,
dass in dem Fenster ein Text
dargestellt wird.
Parameter 1 ist der Geräte-
kontext, Parameter 2 die
die X- Koordinate, an
der der Text im Fenster
beginnen soll, Parameter 3
die Y-Koordinate, Parameter 4
erwartet den eigentlichen
Text und Parameter 5 dessen
Länge. Bei den Parametern 2
und 3 teilen wir die Breite
und die Höhe des
Arbeitsbereichs durch 2, um
in der Mitte des Fensters zu
schreiben, dazu ziehen wir
noch je ein paar Pixel ab um
den Text etwas nach links und
nach oben zu verschieben,
schließlich soll nicht der
Anfang des Textes, sondern
seine Mitte in der Mitte des
Fensters sein. */
ReleaseDC(hwnd, hdc); // Gerätekontexte muss man nach Gebrauch
// wieder freigeben, wenn man die Absturz-
// warscheinlichkeit gering halten möchte.
return(0);
} break;
case WM_DESTROY: /* Bei der Nachricht, dass das Fenster zerstört /
geschlossen wurde, geben wir dem Betriebssystem mit
PostQuitMessage() den Auftrag, das Programm zu
beenden. Schließlich soll es ja nicht mehr laufen,
wenn der Nutzer das einzige Fenster schließt. */
{PostQuitMessage(0); /* die 0 sagt Windows, das unser Programm vom
Befehlshaber den Befehl zum geordneten Rückzug
bekam und nicht etwa die heillose wilde Flucht
ergreift, sprich abstürzt. */
return(0);
} break;
default:break;
} // switch
return (DefWindowProc(hwnd, message, wparam, lparam)); /* Nachrichten,
die wir nicht
selbst verar-
beiten, arbei-
tet Windows
freundlicher-
weise für uns
ab, wenn wir
diese Funktion
aufrufen. Die
Parameter sind
mit denen von
WindowProc
identisch.*/
} // WindowProc
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst,
LPSTR lpcmdline, int ncmdshow)
{
WNDCLASSEX winclass; /* eine Struktur vom Typ WNDCLASSEX wird deklariert
(damit wir eine Klasse für das zu erzeugende
Fenster haben) */
HWND hwnd; /* speichert eindeutige Identifikationsmöglichkeit unseres
Fensters unter Windows, wird in späteren Programmen
oft von uns genutzt*/
MSG message; // Variable, die bei der Verarbeitung von Windows-
// Nachrichten benötigt wird
const char szclassname[] = "USF 4 ever"; /* Der Name der Fensterklasse
Es ist egal, wie er lautet, aber irgend einen
Namen brauchen wir (leider).*/
winclass.cbSize = sizeof(WNDCLASSEX); // Der Struktur wird ihre
//eigene Größe mitgeteilt
winclass.style = CS_HREDRAW | CS_VREDRAW; /* Neuzeichnen des
Fensters horizontal wie vertikal bei seiner
Verschiebung durch den Nutzer */
winclass.lpfnWndProc = WindowProc; // Ein Zeiger auf die CALLBACK Funktion
winclass.cbClsExtra = 0; // Bei Bedarf können hier Extra-Infos für die
// Fensterklasse angegeben werden
winclass.cbWndExtra = 0; // und hier Extra-Infos für das Fenster
// Wir benötigen beides nicht
winclass.hInstance = hinst; // Der Struktur wird gesagt, zu welchem
// Programm sie überhaupt gehört
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* Der Struktur
wird ein Icon übergeben, welches später oben links
in der Titelleiste angezeigt wird. Im ersten
Parameter von LoadIcon muss angegeben werden,
wo das Icon zu finden ist. Wenn NULL übergeben
wird, wird bei den Standardt-Icons von Windows
gesucht.
Der zweite Parameter ist der Name des Icons. */
winclass.hCursor = LoadCursor(NULL, IDC_ARROW); /* Hier wird der
gewünschte Cursor übergeben. Der erste Parameter
gibt wieder an, wo er zu finden ist, der zweite
wieder den Namen. Es gibt ausser dem ARROW noch
APPSTARTING, CROSS, IBEAM, NO, UPARROW, WAIT und
weitere (natürlich immer mit dem IDC am
Namensanfang).*/
winclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); /* Der
Hintergrund des Fensters soll weiß eingefärbt
werden. Alternativ ist auch BLACK_BRUSH oder
möglich. */
winclass.lpszMenuName = NULL; // Der Name des Menüs, falls man eines hat,
// benötigen wir aber nicht.
winclass.lpszClassName = szclassname; // Der Name der Fensterklasse
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* Noch ein
Icon, diesmal für die minimierte Version des
Programms auf der Taskleiste. */
if (!RegisterClassEx(&winclass)) /* Tja, nicht nur Windows XP muss bei
Microsoft registriert werden, sondern
auch unsere Fensterklasse bei Windows*/
return(0); /* Wenn die Registrierung scheitert,
brechen wir unsereWinMain, also unser
ganzes Programm ab, denn dann haben
wir auch kein Fenster*/
if (! // wenn CreateWindowEx scheitert, wird das Programm beendet
(hwnd = CreateWindowEx( /* die eigentliche Erzeugung des Fensters
als Objekt unserer Fensterklasse */
NULL, // erweiterter Fensterstil, für uns
// uninteressant
szclassname, // Der Name der Fensterklasse
"Ein Windows Fenster", /* Name des
Fensters, wird in der Titelleiste
angezeigt */
WS_OVERLAPPEDWINDOW | WS_VISIBLE, /* Das
Aussehen des Fensters
- OVERLAPPEDWINDOW sorgt für
Vergrößern und Verkleinern
Schaltflächen, Rahmen und System-
menü, VISIBLE dafür, dass das
Fenster nach der Initialisierung
sofort sichtbar ist. */
0,0, /* Position des Fensters auf der
X- und der Y-Achse in Pixeln,
ausgehend von der Ecke links oben
im Bildschirm*/
400,300, // Breite und Höhe des Fensters
// in Pixeln
NULL, // Vaterfenster, wenn vorhanden
NULL, // Menu, wenn vorhanden
hinst, /* das Fenster wird informiert, zu
welchem Programm es überhaupt
gehört */
NULL // für uns unwichtige Zusatzinfos
)
)
)
return(0);
while(GetMessage(&message,NULL,0,0)) /* Solange Nachrichten von Windows
an unser Programm da sind, fragen
wir sie der Reihe nach ab.
Parameter 1 ist die Adresse an
die Nachricht gespeichert ist,
Parameter 2 will wissen, für
welches Fenster Nachrichten
abgefragt werden sollen (hier
könnten wir hwnd, das Handle
unseres Fensters angeben, aber
wenn wir NULL angeben, können
wir alle Nachrichten für das
gesamte Programm auf einmal
abfragen (, was da unser
Programm nur ein Fenster hat,
keinen großen Unterschied
ausmacht)
Parameter 3 und 4 sorgen für
die Reihenfolge, in der die
Nachrichten abgearbeitet werden.
Die beiden Nullen sorgen dafür,
dass sie in der Reihenfolge
abgearbeitet werden, in der sie
ankommen*/
{
TranslateMessage(&message); /* Umwandlung der Nachrichten in ein
Format, welches wir verarbeiten können
*/
DispatchMessage(&message); /* Rückgabe der Nachrichten an Windows,
damit dieses sie an unsere Callback-
Funktion weiterleiten kann ( ich weiß,
erst empfangen, dann zurückschicken, um
sie schließlich doch wieder zu
empfangen, hört sich unsinnig an, ist
aber leider nötig */
} // while
return message.wParam; /* das brauchen wir noch für die
Callback-Funktion, also geben wir es zurück */
} // WinMain
______________________________________________________________________
|
|
Zurück
|