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