003
10.01.2003, 16:07 Uhr
void*
Generic Pointer (Operator)
|
Das erste Problem lösen wir indem wir <tchar.h> includieren. Das andere Problem gehen wir gleich an.
C++: |
#include <windows.h>
// Jetzt den Header mit einbinden! #include <tchar.h>
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); static TCHAR szAppName[] = _T("Fenster"); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WfFu; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = reinterpret_cast(COLOR_WINDOW+ 1); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// Hier geht es weiter mit den Erläuterungen
// Wir Registrieren die erzeugte Fensterklasse RegisterClassEx(&wc);
// Wir erstellen unser Fenster und verwenden die // Funktion CreateWindowEx() HWND hWnd = CreateWindowEx( // Steht für erweiterte Stile (in Bezug auf Fenster) WS_EX_CLIENTEDGE, // Hier wird der Name des Fenster übergeben szAppName, _T("Unser erstes Fenster"), // Der Stil überlappend wird angegeben WS_OVERLAPPEDWINDOW, // Jetzt kommen vier Angaben zur Bildschirmposition // d.h. die Position und Größe des Fenster // welche wir in unserem Beispiel alle als Standart belassen CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, // Dieses Argument gibt an das unser Fenster kein untergeordnetes // Fenster ist NULL, // Wir benötigen kein Menü für unsere Anwendung NULL, // Die Zugriffsnummer für unser Fenster wird erstellt, welche // Windows uns zugewiesen hat hInstance, // Das letze Argument bleibt NULL da wir kein Datum der // Fenstererstellung brauchen NULL);
// Jetzt wird es Zeit unser Fenster anzuzeigen ShowWindow(hWnd, nCmdShow); // Sobald sich etwas am Fenster ändert wird neu gezeichnet // z.B. wenn wir die Größe des Fenster mit der Maus verändern UpdateWindow(hWnd);
// Hier implementieren wir die letzte Aufgabe unserer WinMain() // Funktion, sendet Windows an uns eine Nachricht, brauchen wir // eine Schnittstelle, wir müssen also eine Nachrichtenschleife einfügen // Windows Nachrichtenstruktur MSG msg;
// Empfangen der Nachrichten while (GetMessage(&msg,NULL, 0, 0) == TRUE) { // Übersetzen was ankommt TranslateMessage(&msg); // Jetzt tritt unser Dispatcher in Aktion und verteilt die Sache DispatchMessage(&msg); }
// Schluß aus vorbei, besuchen wir mal wieder Windows return msg.wParam; }
|
Der Spaß hat aber seinen Höhepunkt noch nicht erreicht! Wir erinnern uns, haben wir nicht zwei Funktionen, welche ein Programm im Grundgerüst braucht?
Also die Nachrichtenverarbeitungsfunktion muss noch erstellt werden.
Wir müssen zunächst einen Prototypen der WfFu() erstellen, welcher wie folgt aufgebaut ist.
C++: |
LRESULT CALLBACK WfFu // Ermitteln des Fensters, welches die Nachricht auslöste (HWND hWnd, // Nachrichten ID, gibt den Typ der Nachricht an UINT message, // Zusatzinfo, hängt von der Art der Nachricht ab WPARAM wParam, // Zusatzinfo, hängt von der Art der Nachricht ab LPARAM lParam);
|
Diese Funktionsdefinition müssen wir in unser Programm aufnehmen und machen wie folgt weiter:
C++: |
#include <windows.h> #include <tchar.h>
// Den Prototyp von WfFu definieren! LRESULT CALLBACK WfFu(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); static TCHAR szAppName[] = _T("Fenster"); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WfFu; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, szAppName, _T("Unser erstes Fenster"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg,NULL, 0, 0) == TRUE) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
// Hier geht es weiter mit den Erläuterungen // Unsere globale Klasse programmieren wir so: LRESULT CALLBACK WfFu(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam) { // Wir verarbeiten die ausgewählte Nachricht switch (message) { // Die Nachricht soll unser Fenster neu zeichnen case WM_PAINT: { // Struktur für den neu zu zeichnenden Bereich festlegen // Wir erzeugen den Grätekontex, ist verantwortlich für // die Verbindung der einzelnen Geräte, bei uns der Bildschirm PAINTSTRUCT paintst;
// Wir bereiten das Fenster zum zeichnen vor HDC hDC = BeginPaint(hWnd, &paintst); // Innenbereich unseres Fensters ermitteln, rcClient ist ein Zeiger RECT rcClient; // Ermitteln der Koordinaten unseres Fenster ab sofort können wir über // den Innenbereich verfügen und damit arbeiten (Text ausgeben u.s.w.) GetClientRect(hWnd, &rcClient); // Hier speichern wir den Modus vom Texthintergrund int nOldBkMode = SetBkMode(hDC, TRANSPARENT); // Als nächstes wird die Textfarbe festgelegt bei uns die Systemfarbe COLORREF clrOldTextColor = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); // Wir wollen nun etwas Text in das Fenster zaubern DrawText( // Unser Gerätekontex hDC, // Der Text welcher ausgegeben wird _T("Hier erfolgt die Textausgabe"), // Eine mit Null endende Zeichenfolge -1, // Einen rechteckigen Text erzeugen &rcClient, // Das ganze wird eine einzelne Zeile DT_SINGLELINE| // Ausgabe erfolgt horizontal zentriert DT_CENTER | // Ausgabe erfolgt vertikal zentriert DT_VCENTER ); // Wir ersetzen die Textfarbe SetTextColor(hDC, clrOldTextColor); // und nun auch die des Texthintergrundes SetBkMode(hDC, nOldBkMode); // Genug gezeichnet, Ende des FensterNeuZeichnens
EndPaint(hWnd, &paintst);
return 0; }
// Das Fenster wird gelöscht (zerstört) case WM_DESTROY: // Die Anwendung wird beendet PostQuitMessage(0); return 0;
// wenn sonstige Nachrichten ankommen // rufe bitte standardmäßige Nachrichtenbehandlung auf und // lasse mich damit zufrieden default: return DefWindowProc(hWnd, message, wParam, lParam); } }
|
So. Glückwunsch die erste Windowsanwendung ist erstellt. Wer Lust hat kann mir einmal mitteilen, wie dieser Beitrag angekommen ist. Mich würde interessieren ob die Verständlichkeit gegeben ist, oder was verändert werden muß! -- Gruß void* |