Tutorial 2_2

Ein Windows Fenster

______________________________________________________________________
// 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