[vc6] Linie/Polygon zeichnen ohne GDI+
-
Hallo zusammen.
Ich muss eine Linie, bzw. später ein Polygon, zeichnen einzig mit C++ u. MFC. Fragt bitte nicht warum, is einfach so.
Folgendes hab ich bisher:
void CView::OnLButtonDown(UINT nFlags, CPoint point) { m_down = point; SetCapture(); }void CView::OnMouseMove(UINT nFlags, CPoint point) { ClientDC dc(this); CRect rect ( m_down.x, m_down.y, m_last.x, m_last.y ); dcMoveTo ( rect.TopLeft() ); dc.LineTo ( rect.BottomRight() ); m_last = point; }void CView::OnLButtonUp(UINT nFlags, CPoint point) { ::ReleaseCapture(); }Is natürlich nur das wensentliche. Die m_-Komponenten sind vom Typ CPoint.
Folgendes tritt auf:
Mit jeder Mausbewegung wird eine neue Linie gezeichnet. Soll heissen, dass der gesamte Bildschirm bei ausgiebigen Kreisen mit der Maus voll gezeichnet wird.Leider bin ich in Sachen MFC nicht unbedingt der Belesenste...Kann wer unter die Arme greifen?
m.
-
m.trix schrieb:
Folgendes tritt auf:
Mit jeder Mausbewegung wird eine neue Linie gezeichnet. Soll heissen, dass der gesamte Bildschirm bei ausgiebigen Kreisen mit der Maus voll gezeichnet wird.Leider bin ich in Sachen MFC nicht unbedingt der Belesenste...Kann wer unter die Arme greifen?
m.
Jo klar, genau das hast du oben ja auch programmiert.

Wenn du die Linie nur dann malen willst, wenn die Maustaste losgelassen wird, dann wüde ich alles aus OnMouseMove in OnLButtonUp verlagern.PS: Das wohl genialste Tutorial zum Zeichnen mit MFC: Scribble
-
Hallo estartu!
Richtig, so seh ich das auch. Was du vorschlägst hat aber den Nachteil, dass die Linie während die Maus bewegt wird nicht sichtbar ist. Soll sozusagen 'online' passieren. Wie bei Paint etc. wenn man Linien zeichnet.
Scribble hab ich mir auch schon angeschaut, geb dir recht das es wirklich gut ist. Mein Problem wird allerdings nicht behoben. Es gibt auch noch DRAWCLI aber da komm ich nicht völlig dahinter wie es da gemacht wird. Und wenn ich was nicht versteh kopier ichs nicht einfach.
m.
-
m.trix schrieb:
Hallo estartu!
Richtig, so seh ich das auch. Was du vorschlägst hat aber den Nachteil, dass die Linie während die Maus bewegt wird nicht sichtbar ist. Soll sozusagen 'online' passieren. Wie bei Paint etc. wenn man Linien zeichnet.
Da musst du dir glaubich die Position der letzten Linie merken und bevor du die neue malst, malst du die alte aber mit der Hintergrundfarbe.

Wird nur dann kompliziert, wenn der Hintergrund nicht mehr nur eine leere Fläche ist sondern da z.B. schon eine Linie ist. Dann musst du dir wohl alle Linien merken und immer neu malen... das fängt dann aber wieder an zu flackern. Da gibts dann aber auch wieder Möglichkeiten das zu verhindern, ich glaube das Stichwort ist MemDC.
Okay, und da hören meine Kenntnisse dann endgültig auf.
-
m.trix schrieb:
Richtig, so seh ich das auch. Was du vorschlägst hat aber den Nachteil, dass die Linie während die Maus bewegt wird nicht sichtbar ist. Soll sozusagen 'online' passieren. Wie bei Paint etc. wenn man Linien zeichnet.
Zeig doch mal Code! Auch wenn ich in der OnMouseMove was auf mein Fenster zeichne, ist es sofort da. Klingt eher als würdest du was falsch machen.
Dein nächstes Problem: wenn das Fenster minimiert wird und dann wieder geöffnet wird, ist alles weg. Du musst dir die Linien merken.
Entweder machst dir ne kleine Klasse und fügst ein vector zu der zeichnenden KLasse hinzu. Oder du merkst dir das Bild in einem MemDC und blittest diesen dann immer auf das Fenster.@estartu: Solch ein Rubberband bekommt man gan zeasy mit dem CClientDC::SetROP2 hin. In diesem Zeichenmodus werden die Pixel der Linie aus einer xor-Logik mit den bestehden Farbpunkten berechnet. Zeichne ich die Linie an derselben Stelle ein zweites mal in genau diesem Modus, dann ist der alte Inhalt wieder da, als hätte ich nie eine Linie gezeichnet.
-
Der Code ist wie oben beschrieben. Klar wird in der ::OnMouseMove(...) eine Line gezeichnet. Aber zu jeder Bewegung eine Linie. Was estartu vorgeschlagen hat (das Zeichnen in die ::OnLButtonUp(...) hat den Nachteil, dass eine Linie wirklich erst gezeichnet wird wenn die Maustaste losgelassen wird. So soll es aber nicht sein.
Besteht denn die Möglichkeit, das 'alte' CRect in das die vorherige Linie gezeichnet wurde derart ungültig zu machen, dass die Linie nicht mehr sichtbar ist? Hierzu is vllt gut zu wissen, dass ich verschiedene Hintergrundfarben hab. Daher wird das übermalen wohl schnell zum Flackern anfangen. Wie ist denn das bei Paint gelöst? Weis das jemand?
-
Pellaeon schrieb:
@estartu: Solch ein Rubberband bekommt man gan zeasy mit dem CClientDC::SetROP2 hin. In diesem Zeichenmodus werden die Pixel der Linie aus einer xor-Logik mit den bestehden Farbpunkten berechnet. Zeichne ich die Linie an derselben Stelle ein zweites mal in genau diesem Modus, dann ist der alte Inhalt wieder da, als hätte ich nie eine Linie gezeichnet.
Ah cool, das muss ich mir mal merken.

-
Im Drawcli-Beispiel werden die jeweiligen Linien erst in der ::Draw(...) des jeweiligen Objekts (Viereck, Polygon etc.) gezeichnet und nicht direkt in der View. Die ::Draw(...) wird aus der ::OnDraw(...) aufgerufen. Hier komm ich allerdings nie vorbei. Kann des was damit zusammenhängen, dass mit jeder Mausbewegung und neuem Punkt bei mir (::OnMouseMove(...)) immer wieder neue Linie gepinselt werden?
Bin echt am wahnsinnig werden. Kann doch gar ned so schwer sein, oder?
-
So, hier die Lösung:
void CView::OnMouseMove ( UINT nFlags, CPoint point ) { ClientDC dc ( this ); // löschen und 'zeichnen' altes rechteck dc.SetROP2 ( R2_NOT ); // R2_NOT: pixel invers von pencil CRect rect ( m_down.x, m_down.y, m_last.x, m_last.y ); dc.MoveTo ( rect.TopLeft() ); dc.LineTo ( rect.BottomRight() ); // setzen und zeichnen neues rechteck rect.SetRect ( m_down.x, m_down.y, point.x, point.y ); dc.MoveTo ( rect.TopLeft() ); dc.LineTo ( rect.BottomRight() ); ReleaseDC ( &dc ); // freigeben m_last = point; // neue position merken }Wie gesagt, ist längst nicht der komplette Code (speichern d. Punkte f. Polyline etc.) und alles andere ist wie im ersten Post unverändert. Mit Verschiedenen Hintergründen klappts auch wunderbar.
Merce!
m.