Zeichnen nach Tastatureingabe
-
Hallo...
Bin WinAPI-Neuling und kämpfe mit einem Verständnisproblem:
Das hab ich bereits: 3 farbige Linien auf schwarzem Hintergrund mit Text in der
entsprechenden Farbe.Das möchte ich: Eine Linie mit Text nach Aufruf des Programms, nach Eingabe der
VK_NUMPAD1-Taste wird die nächste farbige Linie mit Text ausgegeben, usw...Habe nun schon alles mögliche (unmögliche, sonst würds ja gehen
) mit WM_KEYDOWN probiert... ich kriegs nich hin. (Programm schließt sich nach betätigung irgendeiner Taste.)Wie müssten WM_PAINT + WM_KEYDOWN aufgebaut sein, damit das funzt?
(habe ich mir schon mehrere Tuts angesehen und nichts vergleichbares gefunden)Wäre toll könnte mir jemand auf die Sprünge helfen.
Danke + Grüße
Cloudcreature
-
zeig doch mal dein code

vorschlag:
// winproc static int nLine = 0; // .. case WM_KEYDOWN: // taste die du willst // nLine hochzählen ++nLine; case WM_PAINT: // nLine hält die anzahl der linien die gezeichnet werden sollen // nLine * zeichnen
-
Hätt ich gleich machen sollen!
#include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); char szClassName[] = "WindowsApp"; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; MSG messages; WNDCLASSEX wincl; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); if (!RegisterClassEx (&wincl)) return 0; hwnd = CreateWindowEx( 0, szClassName, "Lines", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 320, 220, HWND_DESKTOP, NULL, hThisInstance, NULL ); ShowWindow (hwnd, nFunsterStil); while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return messages.wParam; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; HPEN hpen; char rl[] = " Rote Linie"; char gl[] = "Grüne Linie"; char bl[] = "Blaue Linie"; switch (message) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, RGB(255,0,0)); TextOut(hdc, 110, 20, rl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(255,0,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 40, NULL); LineTo(hdc, 300, 40); DeleteObject(hpen); SetTextColor(hdc, RGB(0,255,0)); TextOut(hdc, 110, 70, gl, sizeof(gl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,255,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 90, NULL); LineTo(hdc, 300, 90); DeleteObject(hpen); SetTextColor(hdc, RGB(0,0,255)); TextOut(hdc, 110, 120, bl, sizeof(bl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,0,255)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 140, NULL); LineTo(hdc, 300, 140); DeleteObject(hpen); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage (0); break; default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }So siehts im Moment aus. Ich möchte, dass nach Aufruf des Progs die rote Linie angezeigt wird, nach Betätigung der Taste 1 die grüne, nach 2 die blaue, bei 0 wieder die rote (natürlich immer mit entsprechendem Text und der richtigen Farbe).
Hatte zuerst probiert, die meisten WM_PAINT-Sachen nach WM_KEYDOWN zu verschieben, weil mir eben nicht klar ist, wie sonst WM_PAINT auf einen Tastendruck reagiert.
Ach hey... diese ganze API-Geschichte ist halt echt Neuland.

edit: Syntaxcoloring
-
Wenn dein Programm beim Tastendruck beendet wird nehme ich an, dass du einfach das break; vergessen hast

-
@flenders: Nein, die breaks waren schon da... denke, ich hatte ein return 0 vergessen. Nun schließt es sich nicht mehr. jippi
Aber das löst mein ursprüngliches Problem nicht.

Denn eine Reaktion auf einen Tastendruck gibt es nicht.
Eigentlich wollte ich das ja vermeiden, aber was solls... als Neuling wird man ja wohl ein paar Fehler machen dürfen? Also poste ich mal einen Auszug aus meinem Pseudocode:switch (message) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, RGB(255,0,0)); TextOut(hdc, 110, 20, rl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(255,0,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 40, NULL); LineTo(hdc, 300, 40); DeleteObject(hpen); EndPaint(hwnd, &ps); case WM_KEYDOWN: { switch (wParam) { case VK_NUMPAD1: SetTextColor(hdc, RGB(0,255,0)); TextOut(hdc, 110, 70, gl, sizeof(gl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,255,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 90, NULL); LineTo(hdc, 300, 90); DeleteObject(hpen); InvalidateRect(hwnd, NULL, TRUE); break; case VK_NUMPAD2: SetTextColor(hdc, RGB(0,0,255)); TextOut(hdc, 110, 120, bl, sizeof(bl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,0,255)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 140, NULL); LineTo(hdc, 300, 140); DeleteObject(hpen); InvalidateRect(hwnd, NULL, TRUE); break; case VK_NUMPAD0: SetTextColor(hdc, RGB(255,0,0)); TextOut(hdc, 110, 20, rl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(255,0,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 40, NULL); LineTo(hdc, 300, 40); DeleteObject(hpen); InvalidateRect(hwnd, NULL, TRUE); break; } } return 0;Kann das so bzw. so ähnlich funktionieren? (Blöde Frage... tut es ja nicht *gg*)
Wie muss ich das umgestalten?
-
Im Normallfall muss am Ende jedes case-Zweiges ein break oder return stehen - das ist z.B. bei WM_PAINT bei dir nicht der Fall.
-
Hinter EndPaint(hwnd, &ps); fehlt ein break;
Du zeichnest nach "case VK_NUMPAD1:" in den DeviceContext "hdc", aber du hast hdc nirgendswo vorher initialisiert. Die Zeichenoperationen schlagen deshalb alle fehl...
Durch "InvalidateRect(hwnd, NULL, TRUE);" wird eine WM_PAINT-Nachricht an dein Fenster gesendet und alles was du also vorher gezeichnet hast wird gelöscht.Du solltest alle Zeichenoperationen in WM_PAINT machen, WM_PAINT wird an dein Fenster immer gesendet wenn Windows meint dein Fenster müsste neu-gezeichnet werden (z.B. wenn ein anderes Fenster dein Fenster verdeckt hatte oder wenn dein Fenster vergrößert oder verkleinert wird...) - Alles was du vorher woanders gezeichnet hättest würde dann immer verloren gehen da Windows im Normalfall bevor es die WM_PAINT-Nachricht sendet dein gesamtes Fenster einfach mit der Hintergrundfarbe übermalt...
-
Habs nun doch noch hinbekommen!

#include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); char szClassName[] = "WindowsApp"; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; MSG messages; WNDCLASSEX wincl; wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); if (!RegisterClassEx (&wincl)) return 0; hwnd = CreateWindowEx( 0, szClassName, "Lines", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 320, 220, HWND_DESKTOP, NULL, hThisInstance, NULL ); ShowWindow (hwnd, nFunsterStil); while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return messages.wParam; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int i=0; switch (message) { case WM_KEYDOWN: { switch (wParam) { case VK_NUMPAD0: i=0; break; case VK_NUMPAD1: i=1; break; case VK_NUMPAD2: i=2; break; case VK_NUMPAD3: i=3; break; } InvalidateRect(hwnd, NULL, TRUE); return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; HPEN hpen; char rl[] = " Rote Linie"; char gl[] = "Grüne Linie"; char bl[] = "Blaue Linie"; hdc = BeginPaint(hwnd, &ps); SetBkMode(hdc, TRANSPARENT); if(i == 1){ // Taste 1 = Rot SetTextColor(hdc, RGB(255,0,0)); TextOut(hdc, 110, 20, rl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(255,0,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 40, NULL); LineTo(hdc, 300, 40); DeleteObject(hpen); } else if(i == 2){ // Taste 2 = Grün SetTextColor(hdc, RGB(0,255,0)); TextOut(hdc, 110, 70, gl, sizeof(bl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,255,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 90, NULL); LineTo(hdc, 300, 90); DeleteObject(hpen); } else if(i == 3){ // Taste 3 = Blau SetTextColor(hdc, RGB(0,0,255)); TextOut(hdc, 110, 120, bl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,0,255)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 140, NULL); LineTo(hdc, 300, 140); DeleteObject(hpen); } else if(i == 0){ // Taste 0 = Alle Farben SetTextColor(hdc, RGB(255,0,0)); // Default = " TextOut(hdc, 110, 20, rl, sizeof(rl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(255,0,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 40, NULL); LineTo(hdc, 300, 40); DeleteObject(hpen); SetTextColor(hdc, RGB(0,255,0)); TextOut(hdc, 110, 70, gl, sizeof(gl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,255,0)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 90, NULL); LineTo(hdc, 300, 90); DeleteObject(hpen); SetTextColor(hdc, RGB(0,0,255)); TextOut(hdc, 110, 120, bl, sizeof(bl)-1); hpen = CreatePen(PS_SOLID, 0, RGB(0,0,255)); SelectObject(hdc, hpen); MoveToEx(hdc, 10, 140, NULL); LineTo(hdc, 300, 140); DeleteObject(hpen); } EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: PostQuitMessage (0); return 0; default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }Danke euch allen für eure Hilfe!
Grüße