GDI+ Shape mit Maus bewegen funktioniert bei Rectangle aber nicht bei Line!

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Duster.

    GDI+ Shape mit Maus bewegen funktioniert bei Rectangle aber nicht bei Line!

    Hallo zusammen,

    ich benötige Eure Hilfe bei folgendem Problem.
    Ich habe ein kleines Testprogramm geschrieben das ein Rectangle zeichnet welches ich mit der Maus auswählen und verschieben kann. Das funktioniert :) .

    Das gleiche versuche ich in einem weiteren kleinen Testcode mit einer Line. Das funktioniert nicht :( .

    Ich probiere da jetzt schon eine geraume Weile dran rum. Mir ist der Gedanke gekommen dass die Sache nicht funktioniert da die Line keine Fläche wie das Rectangle hat und der Grapg der Line und der des Rectangles nicht auswählbar zu sein scheint. Die einzige Lösung scheint mir zu sein für den Start- und Endpunkt der Line je einen Anfasser zu zeichnen und zwar mit einer Figur die eine Fläche hat (Rectangle, Ellipse).
    Beim anklicken mit der linken Maustaste dann die Anfasser samt Line zu verschieben und mit der rechten Maustaste z.B. Längenänderungen vorzunehmen.

    Oder gibt es da eine bessere Möglichkeit Shapes ohne eine Fläche auszuwählen?

    Hier zuerst der Code des funktionierenden Programms mit dem Rectangle dann dernicht funktionierende Line-Code.

    Rectangle:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. 'Start der Drag-Operation.
    4. Private _startPoint As Point
    5. 'Befindet sich die location innerhalb des Rectangles(_box).
    6. Private _locInBox As Boolean
    7. 'Koordinaten der _box
    8. Private _box As New Rectangle(200, 200, 50, 50)
    9. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    10. If MouseButtons = MouseButtons.Left Then
    11. Dim myLocation As Point = e.Location
    12. 'Startpunkt der draw Operation merken
    13. _startPoint = myLocation
    14. 'Muss hier initialisiert werden sonst verliert der Mauszeiger bei zu schnellem ziehen die _box
    15. _locInBox = IsLocationInBox(myLocation)
    16. End If
    17. End Sub
    18. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    19. If MouseButtons = MouseButtons.Left Then
    20. If _locInBox = True Then
    21. Dim myLocation As Point = e.Location
    22. InvalidateRectangle(_box) 'Neu zeichnen der alten _box Location.
    23. _box.Offset(myLocation.X - _startPoint.X, myLocation.Y - _startPoint.Y) '_box mit MouseZeiger bewegen.
    24. _startPoint = myLocation 'Startpunkt für den nächsten Drag festlegen.
    25. InvalidateRectangle(_box) 'Neu zeichnen der neuen _box Location.
    26. End If
    27. End If
    28. End Sub
    29. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    30. e.Graphics.DrawRectangle(Pens.Black, _box)
    31. End Sub
    32. Private Function IsLocationInBox(myLocation As Point) As Boolean
    33. Dim result As Boolean = False 'Für den Fall dass es keine StandardBox gibt.
    34. If _box.Contains(myLocation) Then
    35. result = True 'Angefragte Location liegt in der _box.
    36. End If
    37. Return result
    38. End Function
    39. Private Sub InvalidateRectangle( box As Rectangle)
    40. box.Inflate(10, 10)
    41. Invalidate(box)
    42. End Sub
    43. End Class



    Line:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. 'Start der Drag-Operation.
    4. Private _lineStartPoint As Point
    5. 'Befindet sich die location innerhalb des Rectangles(_line).
    6. Private _lineLocInBox As Boolean
    7. 'Koordinaten der _line
    8. Private _line As Point() = {New Point (100, 100), New Point ( 250, 100)}
    9. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    10. If MouseButtons = MouseButtons.Left Then
    11. Dim lineLocation As Point = e.Location
    12. 'Startpunkt der draw Operation merken
    13. _lineStartPoint= lineLocation
    14. 'Muss hier initialisiert werden sonst verliert der Mauszeiger bei zu schnellem ziehen die _box
    15. _lineLocInBox = IsLocationInLine(lineLocation)
    16. End If
    17. End Sub
    18. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    19. If MouseButtons = MouseButtons.Left Then
    20. If _lineLocInBox = True Then
    21. Dim lineLocation As Point = e.Location
    22. _line(0).Offset(lineLocation.X - _lineStartPoint.X, lineLocation.Y - _lineStartPoint.Y) '_line mit MouseZeiger bewegen.
    23. _line(1).Offset(lineLocation.X - _lineStartPoint.X, lineLocation.Y - _lineStartPoint.Y) '_line mit MouseZeiger bewegen.
    24. Invalidate() 'Neu zeichnen
    25. End If
    26. End If
    27. End Sub
    28. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    29. e.Graphics.DrawLine(Pens.Black, _line(0),_line(1))
    30. End Sub
    31. Private Function IsLocationInLine(lineLocation As Point) As Boolean
    32. Dim result As Boolean = False 'Für den Fall dass es keine StandardLine gibt.
    33. If _line.Contains(lineLocation) Then
    34. result = True 'Angefragte Location liegt in der _line
    35. End If
    36. Return result
    37. End Function
    38. End Class



    Vielen Dank für Eure Mühe und Hilfe vorab,
    Duste
    @Duster Welche Dicken- bzw. Breitentoleranz lässt Du für die Linie zu?
    Betrachte die Linie als schmales Rectangle.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Breitentoleranz??? Hmmmmmm!!!!!
    Wo und wie sollte ich das implementieren?
    Um ehrlich zu sein lass ich da gar nichts irgendwie zu. Ich kann mir jetzt nicht vorstellen wie Du das meinst!Als schmales Rechteck vorstellen klingt interessant aber ich steig nicht so ganz durch!

    Update:
    Wenn ich in das Rechteck klicke kann ich die Line tadellos bewegen. Lasse ich den Mausknopf los und klicke wieder in das Rechteck geht es auch tadellos weiter.
    Ein Klick auf die Line funktioniert einfach nicht.
    Kann mir jemand sagen wie es richtig gemacht wird?
    Das Programm habe ich angehängt!

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. 'Start der Drag-Operation.
    4. Private _lineStartPoint As Point
    5. 'Befindet sich die location innerhalb des Rectangles(_box).
    6. Private _rectLocInBox As Boolean
    7. Private _lineLocInLine As Boolean
    8. 'Koordinaten der _box
    9. Private _box As New Rectangle(200, 200, 50, 50)
    10. Private _line As Point() = {New Point (100, 100), New Point ( 250, 100)}
    11. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    12. If MouseButtons = MouseButtons.Left Then
    13. Dim rectLocation As Point = e.Location
    14. Dim lineLocation As Point = e.Location
    15. 'Startpunkt der drag Operation merken
    16. _lineStartPoint = lineLocation
    17. 'Muss hier initialisiert werden sonst verliert der Mauszeiger bei zu schnellem ziehen die _box
    18. _rectLocInBox = IsLocationInBox(rectLocation)
    19. _lineLocInLine = IsLocationInLine(lineLocation)
    20. End If
    21. End Sub
    22. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    23. If MouseButtons = MouseButtons.Left Then
    24. If _rectLocInBox = True Then
    25. Dim lineLocation As Point = e.Location
    26. _line(0).Offset(lineLocation.X -_lineStartPoint.X , lineLocation.Y - _lineStartPoint.Y)
    27. _line(1).Offset(lineLocation.X -_lineStartPoint.X , lineLocation.Y - _lineStartPoint.Y)
    28. _lineStartPoint = lineLocation
    29. Invalidate() 'Neu zeichnen der alten _box Location.
    30. End If
    31. End If
    32. End Sub
    33. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    34. e.Graphics.DrawRectangle(Pens.Black, _box)
    35. e.Graphics.DrawLine(Pens.Black, _line(0),_line(1))
    36. End Sub
    37. Private Function IsLocationInBox(rectLocation As Point) As Boolean
    38. Dim result As Boolean = False 'Für den Fall dass es keine StandardBox gibt.
    39. If _box.Contains(rectLocation) Then
    40. result = True 'Angefragte Location liegt in der _box.
    41. End If
    42. Return result
    43. End Function
    44. Private Function IsLocationInLine(lineLocation As Point) As Boolean
    45. Dim result As Boolean = False 'Für den Fall dass es keine StandardBox gibt.
    46. If _line.Contains(lineLocation) Then
    47. result = True 'Angefragte Location liegt in der _box.
    48. End If
    49. Return result
    50. End Function
    51. End Class




    Viele Grüße,
    Duster
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Duster“ ()

    Duster schrieb:

    Breitentoleranz???
    Rechne Dir um diese beiden Punkte ein Umrechteck mit einer endlichen Fläche und überprüfe, ob die Maus da reinklickt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Duster liegt die Gerade pixel-parallel bzw. -senkrecht oder auch schräg?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    ich bin einen Schritt weiter.
    Wird die Line (mit dem linken MouseButton) angeklickt wir der Klick auf die Line als solcher erkannt, das lasse ich in einer TextBox ausgeben.
    Die Line kann ich auch verschieben aber mit dem Löschen klappt es nicht.
    Wenn ich die Line verschiebe wird hinter Ihr die alte Position nicht gelöscht!
    Im Netz finde ich nur Beispiele mit Figuren die eine Fläche haben Rectangles, Cricles, etc. aber nichts mit Line, Lines oder Beziers!
    Ich schaff das einfach nicht, egal wie ich's versuche ;( !
    Könnt Ihr mir da helfen :?:

    Ich hab das Projekt natürlich auch angehängt!

    Hier das bereinigte Projekt:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Drawing.Drawing2D
    3. Public Class Form1
    4. Private _status As Boolean = True
    5. Private _lineStartPoint As Point
    6. Private _locInLine As Boolean
    7. Private ReadOnly _pen As New Pen(Color.FromArgb (255, 0, 0, 255), 10)
    8. Private myGraphicsPath As New GraphicsPath()
    9. Private _line As Point() = {New Point (500, 250), New Point ( 800, 250)}
    10. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    11. _status = True
    12. End Sub
    13. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    14. MyBase.OnPaint(e)
    15. If _status Then
    16. myGraphicsPath.AddLine(_line(0), _line(1))
    17. e.Graphics.DrawPath(_pen, myGraphicsPath)
    18. end if
    19. End Sub
    20. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    21. Dim lineLocation As Point = e.Location
    22. TxtMouseX.Text = e.X.ToString()
    23. TxtMouseY.Text = e.Y.ToString()
    24. If MouseButtons = MouseButtons.Left Then
    25. If _locInLine = True Then
    26. _line(0).Offset(lineLocation.X -_lineStartPoint.X , lineLocation.Y - _lineStartPoint.Y)
    27. _line(1).Offset(lineLocation.X -_lineStartPoint.X , lineLocation.Y - _lineStartPoint.Y)
    28. _lineStartPoint = lineLocation
    29. End If
    30. End If
    31. Invalidate()
    32. End Sub
    33. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    34. Dim lineLocation As Point = e.Location
    35. If MouseButtons = MouseButtons.Left Then
    36. _lineStartPoint = lineLocation
    37. _locInLine = IsLocationInLine(lineLocation, e)
    38. End If
    39. End Sub
    40. Private Function IsLocationInLine(lineLocation As Point, e As MouseEventArgs) As Boolean
    41. Dim result As Boolean = False 'Für den Fall dass es keine StandardLine gibt.
    42. If myGraphicsPath.IsOutlineVisible(e.X, e.Y ,_pen) = True Then
    43. TxtTest.BackColor = Color.Chartreuse
    44. TxtTest.Text = "> Treffer! <"
    45. result = True 'Angefragte Location liegt in der _line.
    46. Else
    47. TxtTest.Clear()
    48. TxtTest.BackColor = Color.White
    49. End If
    50. Return result
    51. End Function
    52. End Class


    Schein ein ungeliebtes/ komplexes Thema zu sein?

    Vielen Dank für Eure Mühe und Hilfe,
    Duster
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Duster“ ()

    @Duster Dein GraphicsPath wird doch mit einer Flut von Linien befüllt.
    Lösche ihn vorher:

    VB.NET-Quellcode

    1. If _status Then
    2. myGraphicsPath.Trset() ' Dies hier
    3. myGraphicsPath.AddLine(_line(0), _line(1))
    4. e.Graphics.DrawPath(_pen, myGraphicsPath)
    5. end if
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!