mehrere Objekte clickbar

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von klyer.

    mehrere Objekte clickbar

    Hallo Com,
    möchte gern mehrere Objekte (Rectangles), welche in einer For Schleife generiert werden, einzeln clickbar machen.
    Habe mich dazu schon dumm und dusselig im www gesucht und wäre für Links o.a. sehr dankbar.
    Mein Code:

    VB.NET-Quellcode

    1. Private rect As Rectangle
    2. Private pen As Pen = Pens.Black
    3. Public Sub New()
    4. InitializeComponent()
    5. AddHandler Click, AddressOf Form1_Click
    6. End Sub
    7. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    8. MyBase.OnPaint(e)
    9. Dim x As Integer
    10. For x = 0 To 1000 Step 55
    11. Dim blackPen As New Pen(Color.Black, 1)
    12. rect = New Rectangle(x, 0, 50, 50)
    13. e.Graphics.DrawRectangle(blackPen, rect)
    14. Next
    15. End Sub
    16. Private Sub Form1_Click(sender As Object, e As EventArgs)
    17. Dim cursorPos As Point = Me.PointToClient(Cursor.Position)
    18. If rect.Contains(cursorPos) Then
    19. MsgBox("IN")
    20. Else
    21. MsgBox("OUT")
    22. End If
    23. Invalidate()
    24. End Sub​

    In diesem Fall bekommt immer nur das letzte Objekt das Click-Event.
    @klyer Pack die Rectangles in eine List(Of Rectagle) in die Klasse. Die kannst Du abgreifen, um sie zu malen und um das MouseDown-Ereignis abzuchecken.
    Wenn sich die Rechtecke überdecken, musst Du halt alle gefundenen separat behandeln.
    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 Vielen Dank für deine Antwort. Habe den Code folgendermaßen angepasst:

    VB.NET-Quellcode

    1. Dim rectList As New List(Of Rectangle)
    2. Private pen As Pen = Pens.Black
    3. Public Sub New()
    4. InitializeComponent()
    5. For x = 0 To 1000 Step 55
    6. rectList.Add(New Rectangle(x, 0, 50, 50))
    7. Next
    8. AddHandler Click, AddressOf Form1_Click
    9. End Sub
    10. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    11. MyBase.OnPaint(e)
    12. Dim blackPen As New Pen(Color.Black, 1)
    13. For Each Rectangle In rectList
    14. e.Graphics.DrawRectangle(blackPen, Rectangle)
    15. Next
    16. End Sub
    17. Private Sub Form1_Click(sender As Object, e As EventArgs)
    18. Dim cursorPos As Point = Me.PointToClient(Cursor.Position)
    19. Dim isInside = False
    20. For Each Rectangle In rectList
    21. If Rectangle.Contains(cursorPos) Then
    22. isInside = True
    23. Else
    24. isInside = False
    25. End If
    26. Next
    27. If isInside Then
    28. MsgBox("IN")
    29. Else
    30. MsgBox("OUT")
    31. End If
    32. Invalidate()
    33. End Sub

    Gleiches Resultat: Es bekommt immer noch nur das letzte gezeichnete Rectangle das Click-Event.

    klyer schrieb:

    PointToClient
    Lass das mal weg, nimm den Punkt so wie er ist.
    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!
    Du solltest das Rectangle in einer Klasse kapseln. Gib der Klasse dann u. A. eine Property, die ihre gegenwärtige Z-Position speichert. So kannst Du unterscheiden, welches Object oben auf liegt.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    @SpaceyX Es geht mir weniger darum, ob Rectangles übereinander liegen, sondern einfach nur darum das jedes einzelne der ca.20 (in einer Schleife) gezeichneten Rectangles anklickbar ist. Wollte es zu Testzwecken noch nicht in eine Klasse kapseln.
    Oder liegt das Problem daran, dass die Rectangles wie sie momentan gezeichnet werden, "übereinander" liegen?
    Genau daran liegt es. Liegen 2 übereinander oder überlappen dort, wo geclickt wird, so beinhalten logischerweise beide diesen Punkt. Somit musst Du feststellen, welches gemeint ist. In den meisten Fällen ist es das Oberste.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    @klyer Sorry, mein Fehler.
    1. nimm MouseDown, da hast Du die korrekten Koordinaten.
    2. musst Du die Schleife bei einem gefundenen Rechteck verlassen.
    Dies hier funktioniert:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim rectList As New List(Of Rectangle)
    3. Private pen As Pen = Pens.Black
    4. Public Sub New()
    5. InitializeComponent()
    6. For x = 0 To 1000 Step 55
    7. rectList.Add(New Rectangle(x, 0, 50, 50))
    8. Next
    9. End Sub
    10. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    11. MyBase.OnPaint(e)
    12. Dim blackPen As New Pen(Color.Black, 1)
    13. For Each rc In rectList
    14. e.Graphics.DrawRectangle(blackPen, rc)
    15. Next
    16. End Sub
    17. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
    18. Dim cursorPos As Point = e.Location
    19. Dim isInside = False
    20. For Each rc In rectList
    21. If rc.Contains(cursorPos) Then
    22. isInside = True
    23. Exit For
    24. Else
    25. isInside = False
    26. End If
    27. Next
    28. If isInside Then
    29. MsgBox("IN")
    30. Else
    31. MsgBox("OUT")
    32. End If
    33. End Sub
    34. End Class
    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!