Seku
HomeProjekteTutorialsToolsGFXLinksForumGästebuchKontaktImpressumLogin
Stoppt die Vorratsdatenspeicherung - www.vorratsdatenspeicherung.de

tutorial anzeigen

Durch lesen dieses Artikels akzeptieren Sie folgende Nutzungsbedingungen:
Dieser Artikel und alle verwendeten Materialien (Bilder, Quelltexte, etc.) unterliegen dem Copyright des Autors, hier Seku. Das kopieren dieses Artikels, Auszügen oder verwendeten Materialien und Einfügen auf anderen Seiten als dieser (seku.info) ist nur mit einer ausdrücklichen, schriftlichen Einverständniserklärung des Autors erlaubt. Weder Autor noch der Betreiber dieser Seite haften für eventuelle Schäden, die durch diesen Artikel oder herunterladbare Objekte ( > Downloads ) verursacht wurden. Die Richtigkeit dieses Textes ist nicht garantiert.
Herzlich Willkommen im zweiten Teil meiner Tutorialserie. Da wir nun gelernt haben, wie man ein Fenster erstellt und verwaltet, geht es nun daran, diesem auch Texte und Knöpfe hinzuzufügen. Ich sehe keinen Sinn darin, jetzt eine lange Einleitung zu schreiben, weshalb ich jetzt einfach anfangen werde. Ich will nur noch erwähnen, dass man das Kapitel, in dem das Erstellen von Texten erklärt wird, auf keinen Fall überspringen sollte, da der Buttonsteil darauf zurückgreift.

Texte

Im ersten Teil haben wir gelernt, dass jedes Element ein Fenster ist, ganz egal ob ein Fenster, wie man es als Benutzer kennt, Button, Checkbox, Text, etc. Jetzt habe ich es schon verraten; wir brauchen wieder CreateWindow(). Aber was ist der Unterschied bei der Erstellung zwischen einem Text und einem Fenster, wie man es als Benutzer kennt? Die Antwort ist ganz einfach: die Fensterklasse. Windows liefert vorgefertigte Fensterklassen. Die zugehörige Fensterfunktion ist auch so freundlich seinem ParentWindow bericht zu erstatten; also uns. Bleibt noch eine Frage: Wie heißt die vorgefertigte Fensterklasse für Texte? Sie heißt "STATIC". Der Name kann trügen, diese Textfelder sind natürlich nicht statisch. Ein Funktionsaufruf könnte nun so aussehen.

// Einen Text erstellen
HWND hText = CreateWindow("STATIC",
                          "Bla Bla, Lorem Ipsum...",
                          WS_VISIBLE,    // Nicht vergessen!
                          5, 5,
                          200, 30,
                          hWindow,
                          NULL,
                          hInstance,
                          NULL);
    if(!hText)
        return FALSE;

Wenn wir diesen Codeschnipsel hinter die Erstellung des Hauptfensters, aus dem Beispielprogramm des vorherigen Kapitels, einsetzen, werden wir eine böse Überraschung erleben. Das ganze wird dann etwa so aussehen:



Hoppla, was ist da passiert? Nun wir erinnern uns doch noch daran, dass alles aus Fenstern besteht. Wie man sieht, ist das hier auch der Fall, aber leider nicht so, wie wir das wollen. Hier kommt ein weiteres WindowStyle dazu. Neben WS_VISIBLE schreiben wir also noch WS_CHILD, was angibt, dass das Fenster nur ein Element des ParentWindow und kein eigenständiges Fenster ist. Hierbei muss man natürlich aufpassen, dass man auch ein ParentWindow angegeben hat, denn sonst wird das Handle, das wir erhalten NULL sein. Ein Funktionsaufruf könnte nun so aussehen...

// Einen Text erstellen
HWND hText = CreateWindow("STATIC",
                          "Bla Bla, Lorem Ipsum...",
                          WS_CHILD | WS_VISIBLE,    // Nicht vergessen!
                          5, 5,
                          200, 30,
                          hWindow,
                          NULL,
                          hInstance,
                          NULL);
    if(!hText)
        return FALSE;

Der so erstellte Text sieht nun so aus



Schon besser, oder? Aber irgendwas passt uns das noch nicht. Es ist die fette Schrift. Aber das kann man ganz einfach korrigieren. Wir müssen dem Fenster einfach eine Nachricht schicken. Die Nachricht heißt WM_SETFONT. WParam ist das Handle zur Schrift (HFONT), LPARAM ist TRUE. Das ginge dann so:

// Den Text erstellen
HWND hText = [...]

// Für alle die den Prototyp von SendMessage nicht kennen:
// SendMessage(HWND hWindow, unsigned int uiMsg, WPARAM WParam, LPARAM LParam);
//             Das Fenster,  Die Nachricht,      Der WParam,    Der LParam

// Die Schrift setzen
SendMessage(hText, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);

Hier haben wir wieder GetStockObject(). Nur diesmal wollen wir natürlich keine Standardfarbe, sondern die Standardschrift. Ich denke es sollte nun alles klar sein. Nachdem wir aber nun WM_SETFONT kennen, bleibt mir wohl nichts anderes übrig, euch die anderen Nachrichten eines Textes zu nennen.

Nachricht Funktion WParam LParam
WM_GETFONT Gibt ein Handle zur genutzten Schrift zurück. ungenutzt ungenutzt
WM_GETTEXT Gibt den Text als char* zurück. ungenutzt ungenutzt
WM_GETTEXTLENGTH Gibt die Textlänge in Zeichen zurück ungenutzt ungenutzt
WM_SETFONT Setzt eine neue Schrift Handle zur neuen Schrift (HFONT) Wenn TRUE, wird das Fenster sofort neu gemalt.
WM_SETTEXT Setzt einen neuen Text ungenutzt Der neue Text
WM_PAINT Malt das Objekt neu ungenutzt ungenutzt

Buttons

Das war's nun mit dem Text. Jetzt gehen wir über zu Buttons. Jetzt, da wir das Wesentliche schon wissen, muss ich eigentlich nur noch die neue Fensterklasse nennen. Sie heißt "BUTTON". Ich erwähne nur nochmal, dass man nie WS_CHILD vergessen sollte. Buttons können wir die selben Nachrichten schicken wie Texten, ohne Unterschiede
Nehmen wir mal an, alles klappt und der Benutzer drückt den Button. Ich habe bereits mehrmals gesagt, dass der Button seinem Parent dann eine nachricht schickt. Diese heißt WM_COMMAND. Für uns ist dann nur der LParam interessant, da er ein Handle auf den Button ist. Jetzt können wir mit einer einfachen If-Abfrage prüfen, welcher Button gedrückt wurde. Einfach, oder? Ja, so einfach, dass ich hier gar nichts mehr sagen will

Ein Beispielprogramm

Dieses Programm ist eine etwas veränderte Form des Beispielprogramms vom letzten Teil.

/********************************************************
 *                                                      *
 *                                                      *
 *    Main.cpp                                          *
 *    ========                                          *
 *    Autor: Seku                                       *
 *    Zweck: Beispielprogramm für ein Tutorial          *
 *                                                      *
 *                                                      *
 ********************************************************/

#include <Windows.h>

// ======================================================
// Globale Variablen
HINSTANCE        g_hInstance;        // Instanz auf das Programm
HWND             g_hText;            // Instanz auf den Text
HWND             g_hButton1;         // Instanz auf den ersten Button
HWND             g_hButton2;         // Instanz auf den zweiten Button

// ======================================================
// Die Nachrichtenfunktion
LRESULT CALLBACK WindowProc(HWND hWindow,
                            unsigned int uiMsg,
                            WPARAM WParam,
                            LPARAM LParam)
{
        // Die Nachricht durchgehen
        switch(uiMsg)
        {
                case WM_CREATE:
                        // Das Fenster wurde erstellt.
                        break;

                case WM_COMMAND:
                        // Ein Button wurde gedrückt, welcher?
                        if(LParam == (LPARAM)g_hButton1)        // Button1?
                                SendMessage(g_hText, WM_SETTEXT, 0,
                                    (LPARAM)"Hallo Welt\nDas ist der erste Text,\n"
                                            "der Zweite kommt auf Knopfdruck ^^");

                        if(LParam == (LPARAM)g_hButton2)        // Button2?
                                SendMessage(g_hText, WM_SETTEXT, 0,
                                    (LPARAM)"Hallo Welt\nDas ist der zweite Text.\n"
                                            "Durch deinen Knopfdruck hast du\n"
                                            "gerade ein Programm sehr glücklich gemacht\n"
                                            "Der erste Text kommt auf Knopfdruck^^");
                        break;

                case WM_DESTROY:
                        // Das Fenster wird beendet
                        DestroyWindow(hWindow); // Beendet das Fenster
                        UnregisterClass("MySampleClassForMySampleWindow - Seku",
                                        g_hInstance);    // Löscht die Fensterklasse
                        PostQuitMessage(1);
                        break;

                default:
                        break;
        }

        // Die Nachricht an Windows weiterleiten
        return DefWindowProc(hWindow, uiMsg, WParam, LParam);
}

// ======================================================
// Die Hauptfunktion
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   char* pcCmdLine,
                   int iShowCmd)
{
        WNDCLASSEX  WindowClass;             // Die Fensterklasse
        MSG         Message;                 // Die Nachricht
        HWND        hWindow;                 // Das Fenster
        HWND        hButton1, hButton2;      // Die Buttons
        HWND        hText;                   // Der Text

        // Die Programminstanz globalisieren
        g_hInstance = hInstance;

        // Die Fensterklasse erstellen
        ZeroMemory(&WindowClass, sizeof(WNDCLASSEX));        // sonst kann es zu Fehlern kommen
        WindowClass.cbSize          = sizeof(WNDCLASSEX);
        WindowClass.style           = CS_CLASSDC;
        WindowClass.lpfnWndProc     = WindowProc;
        WindowClass.cbClsExtra      = 0;
        WindowClass.cbWndExtra      = 0;
        WindowClass.hInstance       = hInstance;
        WindowClass.hIcon           = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
        WindowClass.hIconSm         = WindowClass.hIcon;
        WindowClass.hCursor         = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_ARROW));
        WindowClass.hbrBackground   = GetSysColorBrush(COLOR_3DFACE);
        WindowClass.lpszMenuName    = NULL;
        WindowClass.lpszClassName   = "MySampleClassForMySampleWindow - Seku";

        // Die Fensterklasse registrieren
        if(!RegisterClassEx(&WindowClass))
        {
                // Fehler!
                return FALSE;
        }

        // Das Fenster erstellen
        hWindow = CreateWindow(WindowClass.lpszClassName,
                               "Testfenster",
                               WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                               50, 50,
                               205, 180,
                               NULL,
                               NULL,
                               hInstance,
                               NULL);
        if(!hWindow)
                return FALSE;

        // Die Buttons erstellen
        hButton1 = CreateWindow("BUTTON", "Text 1 anzeigen",
                       WS_VISIBLE | WS_CHILD, 5, 5, 90, 30,
                       hWindow, NULL, hInstance, NULL);
        if(!hButton1) return FALSE;
        hButton2 = CreateWindow("BUTTON", "Text 2 anzeigen",
                       WS_VISIBLE | WS_CHILD, 100, 5, 90, 30,
                       hWindow, NULL, hInstance, NULL);
        if(!hButton2) return FALSE;

        // Den Text erstellen
        hText = CreateWindow("STATIC", "Hallo Welt\n"
                    "Das ist der erste Text,\nDer Zweite kommt auf Knopfdruck^^",
                    WS_VISIBLE | WS_CHILD, 5, 40, 180, 100, hWindow, NULL, hInstance, NULL);
        if(!hText) return FALSE;

        // Die Handles globalisieren
        g_hButton1 = hButton1;
        g_hButton2 = hButton2;
        g_hText = hText;

        // Die Schrift setzen
        SendMessage(hText, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);
        SendMessage(hButton1, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);
        SendMessage(hButton2, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);

        // Die Fensterschleife starten
        ZeroMemory(&Message, sizeof(MSG)); // sonst kann es zu Fehlern kommen
        while(GetMessage(&Message, NULL, 0, 0))
        {
                // Die Nachricht weiterleiten
                TranslateMessage(&Message);
                DispatchMessage(&Message);
                if(Message.message == WM_QUIT)
                {
                        // Das Fenster soll beendet werden; wir verlassen die Schleife
                        break;
                }
        }

        // Alles OK!
        return TRUE;
}

Wer das kopiert und compilert, wird so ein schönes Fenster bekommen:

Ende

Nun, jetzt wissen wir mal wieder mehr. Was noch bleibt sind diverse, spezifische WindowStyles, aber ich denke, dass man die in der MSDN nachgucken kann. Also dann, bis zum nächsten Teil,

Seku




Alle Inhalte stehen, wenn nicht anders angegeben, unter dem Copyright von Seku.
Für die Inhalte externer Seiten ist der jeweilige Betreiber verantwortlich.
seku.info v.3.2, Benötigte Zeit: 0,252 Sekunde(n)
Ausgeführte mySQL-Anfragen: 0
17:25