Linien über Maus zeichnen
-
Neues Jahr, neues Problem ....
Ich lese grad ein Buch, in dem Grad das zeichnen von einfachen Linien behandelt wird. Jetzt wollte ich in wenig kreativ sein und den Benutzer durch Mausclicks
solche Linie zeichen lassen. Also bei einem Linksclick soll die Position der Maus beim click gespeichert werden und dann bei jeder Mausbewegung vom Startpunkt bis zur aktuellen Mausposition eine Linie gezeichnet werden. Bei einem Rechtsclick soll dann die Linie sozusagen "losgelassen" werden also nicht weiter bei mousemove bis zur Mausposition gehen. Naja die Erklärung war etwas schwammig, aber ich denke der Code zeigt zumindest grob was ich erreichen möchte:HDC hdc; PAINTSTRUCT ps; static bool FirstClick; static POINT StartingPoint; static POINT MousePoint; switch(message) { case WM_CREATE: { FirstClick = true; return 0; } case WM_MOUSEMOVE: { if(FirstClick = false) { MousePoint.x = LOWORD(lParam); MousePoint.y = HIWORD(lParam); PostMessage(hWnd, WM_PAINT, NULL, NULL); } return 0; } case WM_RBUTTONUP: { FirstClick = true; return 0; } case WM_LBUTTONUP: { if(FirstClick = true) { FirstClick = false; } StartingPoint.x = LOWORD(lParam); StartingPoint.y = HIWORD(lParam); return 0; } case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); HPEN Pen1 = CreatePen(PS_SOLID, 4, RGB(0,0,0)); SelectObject(hdc, Pen1); MoveToEx(hdc, StartingPoint.x, StartingPoint.y, NULL); LineTo(hdc, MousePoint.x, MousePoint.y); DeleteObject(Pen1); EndPaint(hWnd, &ps); return 0; }Das Problem besteht einfach darin, dass keine Linie zu sehen ist. Ich habe aber leider keine Ahnung wieso, schließlich wird WM_PAINT ja von mousemove gepostet und sollte dann doch auch richtig bearbeitet werden oder?

Ich hoffe ihr könnt mir da helfen
-
Hm, probier als allererstes mal, alle
if(FirstClick = true)durch
if(FirstClick == true)oder
if(FirstClick)zu ersetzen. Das = bewirkt auch in einer Abfrage eine Zuweisung und hat als Ergebnis true zur Folge.
-
Shit... dachte sowas würde mir ncithmehr passieren

Aber irgendwie wird immernoch nicht gezeichnet.. da muss noch was sein -.-
-
Hast du diesen Fehler auch in WM_MOUSEMOVE verbessert?
-
Ohne Aufruf von SetCapture wirst Du evtl. die WM_LBUTTONUP Nachricht nicht erhalten, wenn der User die Maus außerhalb des Fensters bewegt.
Bitte ReleaseCapture nicht vergessen.
-
Also mir ist aufgefallen, dass die Linie erst gezeichnet wird wenn ich zB. die Fenstergröße verändere. Jetzt hab ich gedacht, dass
PostMessage(hWnd, WM_PAINT, NULL, NULL);aus irgend einem Grund nicht funktionieren würde, also Rückgabe Wert geprüft ob er 0 ist und dann per MessageBox eine Meldung ausgegeben. Allerdings scheint die Funktion erfolgreich zusein, obwohl kein WM_PAINT ausgeführt wird. Hat jemand ne Ahnung wodran das liegen könnte?
Ich hab mal eine zweiten Lösungsweg versucht, der direkt in MOUSE_MOVE zeichnet:
case WM_MOUSEMOVE: { if(FirstClick == false) { MousePoint.x = LOWORD(lParam); MousePoint.y = HIWORD(lParam); hdc = GetDC(hWnd); HPEN Pen1 = CreatePen(PS_SOLID, 4, RGB(0,0,0)); SelectObject(hdc, Pen1); MoveToEx(hdc, StartingPoint.x, StartingPoint.y, NULL); LineTo(hdc, MousePoint.x, MousePoint.y); DeleteObject(Pen1); ReleaseDC(hWnd, hdc); } return 0; }Da ist jetzt das Problem, dass bei jeder mausbewegnung eine Linie gezeichnet wird. Soweit noch richtig, aber ich möchte ja, dass die alten Linien gelöscht werden. Also hab ich das mit einem
InvalidateRect(hWnd, 0, true);vor dem ganzen zeichnen versucht. Jetzt sehe ich aber garkeine Linien mehr

Ich weiß echt nicht wieso das immernoch nicht funktioniert.
-
1. WM_PAINT wird nicht gepostet und sollte niemals gepostet werden:
http://blog.m-ri.de/index.php/2007/12/24/die-unsitte-windows-interne-nachrichten-zu-versenden/
in Deinem Fall heißt das bitte InvalidateRect zu nutzen, oder RedrawWindow.2. Du hast noch nicht verstanden wie Windows funktioniert.
Ein Fenster wird nur im WM_PAINT Handler gezeichnet. Und Du musst selbst dafür sorgen, dass die Daten korrekt gezeichnet werden wenn WM_PAINT aufgerufen wird.
So hast Du es auch gemacht. Gut so.
Wenn Du aber selber das Fenster änderrst musst Du auch InvalidateRect aufrufen (d.h. in WM_MOUSEMOVE und WM_LBUTTONUP).Alter Fensterinhalt wird nicht durch Windows irgendwie zwischengespeichert.
-
Ok, danke. Das hat geholfen. Funktioniert jetzt im Grunde. Den rest schaffe ich wohl alleine, sonst poste ich nochmal.