Kann man Steuerelemente zusammenführen/ bündeln?

  • VB.NET

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

    Kann man Steuerelemente zusammenführen/ bündeln?

    Hallo Leute!

    Ich habe ein UserControl mit dem Name Tab erstellt, was ein TableLayoutPanel zur Anordnung eines Labels und eines Buttons enthält. Um MouseMove- und MouseLeave-Ereignisse auf dem Tab zu verwalten, kann ich das Tab leider nicht direkt ansprechen, sondern führe die Handler für das TableLayoutPanel, das Label und den Button in einer Funktion zusammen, was eine zeitverzögerte und somit unerwünschte Anzeige zur Folge hat. Nutze ich nur die Handles Tab.MouseMove und Tab.MouseLeave, wird leider das zweite Handle aktiv, wenn sich der Mauscursor über dem Label und dem Button befindet und das möchte ich verhindern, da Tab.MouseLeave nur eintreten soll, wenn sich der Cursor wieder außerhalb der Steuerelementegrenzen befindet.

    Leider habe ich bisher keinen passenden Lösungsansatz finden können. Korrigiert mich bitte, wenn ich einen im Forum übersehen habe! Gibt es eine Möglichkeit, die einzelnen Steuerelemente so zusammenzuführen, dass man das Steuerelement im Ganzen ansprechen kann für Handler wie MouseMove, MouseLeave oder MouseDown und nicht die Handler der Untersteuerelemente separat verwalten muss?

    Mein bisheriger Code:

    VB.NET-Quellcode

    1. AddHandler TableLayoutPanel.MouseMove, AddressOf Tab_MouseMove
    2. AddHandler lblTitle.MouseMove, AddressOf Tab_MouseMove
    3. AddHandler btnClose.MouseMove, AddressOf Tab_MouseMove
    4. AddHandler TableLayoutPanel.MouseLeave, AddressOf Tab_MouseLeave
    5. AddHandler lblTitle.MouseLeave, AddressOf Tab_MouseLeave
    6. AddHandler btnClose.MouseLeave, AddressOf Tab_MouseLeave
    7. Private Sub Tab_MouseMove(ByVal sender as Object, ByVal e As System.EventArgs)
    8. End Sub
    9. Private Sub Tab_MouseLeave(ByVal sender as Object, ByVal e As System.EventArgs)
    10. End Sub


    Mein gewüntes Ziel:

    VB.NET-Quellcode

    1. Private Sub Tab_MouseMove(ByVal sender as Object, ByVal e As System.EventArgs) _
    2. Handles Tab.MouseMove
    3. End Sub
    4. Private Sub Tab_MouseLeave(ByVal sender as Object, ByVal e As System.EventArgs) _
    5. Handles Tab.MouseLeave
    6. End Sub


    MfG DocWoric
    Bilder
    • Tab.JPG

      16,96 kB, 276×262, 167 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DocWoric“ () aus folgendem Grund: Genauere Problembeschreibung.

    Willkommen im Forum. :thumbup:
    Welch anspruchsvoller 1. Beitrag von Dir :!:
    Ich hoffe, ich habe Dich richtig verstanden.
    Du hast ein UserControl mit Controls drauf und Du möchtest ggf. die Events der Controls an das Main-Window weitersenden?
    Zunächst einmal kannst Du auch beim UserControl alle Deine Events im Designer anlegen, dann sehen sie genau so wie Dein gewünschtes Ziel aus.
    Dazu musst Du im Designer im Tab Eigenschaften auf den kleinen gelben Blitz in der Toolbar klicken und auf das gewünschte Event doppelklicken.
    Wenn die Events nun an das Main-Window weiterleiten willst, mach es so (wichtig ist WithEvents):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class UserControl1
    2. Public Event UserClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
    3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4. RaiseEvent UserClick(Me, e)
    5. End Sub
    6. End Class

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents MyUserControl As New UserControl1 ' oder über den Designer einfügen
    3. Private Sub MyUserControl_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyUserControl.UserClick
    4. End Sub
    5. End Class
    Bilder
    • Events.jpg

      10,99 kB, 247×164, 283 mal angesehen
    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 RodFromGermany!

    Vielen Dank für Deinen Lösungsansatz. So weit, so klar. Wenn ich Dich richtig verstehe, müsste ich aber dann wieder für jedes der einzelnen untergeordneten Controls im Tab das Event auslösen. Zumindest stelle ich mir das folgendermaßen vor:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Tab
    2. #Region "OnMouseOver"
    3. Public Shadows Event OnMouseOver ...
    4. Sub Me_MouseOver ... Handles Me.MouseMove ... Raise Event OnMouseOver ... End Sub
    5. Sub Label_MouseOver ... Handles Label.MouseMove ... Raise Event OnMouseOver ... End Sub
    6. Sub Button_MouseOver ... Handles Button.MouseMove ... Raise Event OnMouseOver ... End Sub
    7. #End Region
    8. #Region "OnMouseLeave"
    9. Public Shadows Event OnMouseLeave ...
    10. 'Sub's analog OnMouseOver
    11. #End Region
    12. End Class

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents MyTab As New Tab
    3. Private Sub MyTab_MouseOver(...) Handles MyTab.OnMouseOver
    4. MyTab.BackColor = Colors.Green
    5. End Sub
    6. Private Sub MyTab_MouseLeave(...) Handles MyTab.OnMouseLeave
    7. MyTab.BackColor = Colors.Red
    8. End Sub
    9. End Class


    Die Handler für die untergeordneten Steuerelemente sind leider momentan erforderlich, da ich ohne sie sonst beim Überfahren von MyTab) zwar den Hintergrund auf Grün gesetzt bekomme, wenn ich die Maus LANGSAM darüber bewege, weil dessen Margin = 0 und Padding = 1 sind aus Platzgründen. Bewege ich die Maus dann über MyTab, passiert entweder gar nichts (weil zu schnell und das OnMouseMove nicht erkannt wurde) oder Folgendes:

    (1) Der Cursor bewegt sich über MyTab und der Hintergrund wird Grün.
    (2) Ich bewege die Maus weiter und der Cursor befindet sich dann bspw. auf dem Label (soll kein Event auslösen).
    (3) Demzufolge wird auf MyTab selbst OnMouseLeave ausgelöst, weil das System den Label jetzt als aktiv ansieht.
    (4) Dadurch wird der Hintergrund automatisch Rot obwohl sich der Cursor noch im eigentlichen Steuerelement (MyTab) befindet.

    Ich suche quasi nach einer Möglichkeit, bei der es völlig uninteressant ist, über welches untergeordnete Steuerelement ich die Maus bewege, solange sich der Cursor über dem Container-Steuerelemnt MyTab befindet und erst wieder ein Event ausgelöst wird, wenn ich den Container mit der Maus verlasse. Jedoch kann ich die Handler der untergeordneten Steuerelemente nicht einfach löschen, da ich wiederum das ClickEvent benötige.
    Das ist nicht nötig.
    Du kannst Events bündeln:

    VB.NET-Quellcode

    1. Private Sub Button1_MouseMove(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove, Button1.MouseMove, Label1.MouseMove
    2. If sender Is Me Then
    3. ElseIf sender Is Button1 Then
    4. ElseIf sender Is Label1 Then
    5. End If
    6. End Sub
    Allerdings solltest Du die Mauskoordinaten in die des Controls umrechnen, bevor Du sie weiterschickst.
    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!
    Wie es mir scheint, komme ich nicht drum herum, jedes Control mit einem Handle zu versehen. Ich überleg mir da mal noch eine komfortable Lösung. ;)

    Was mich aber jetzt interessieren würde, wie man die Mauskoordinaten in die des Controls umrechnen kann? Ich hatte schon mal das Problem, dass ich ein Kontextmenü im Control einfach nicht an der aktuellen Cursorposition dargestellt bekommen habe. Habs aber gekonnt lösen können, indem ich dem Control das Kontextmenü per Code zugewiesen habe.

    DocWoric schrieb:

    Ich hatte schon mal das Problem, dass ich ein Kontextmenü im Control einfach nicht an der aktuellen Cursorposition dargestellt bekommen habe.
    Da hast Du was falsch gemacht. Das erledigt das System für Dich, indem Du dem Control im Designer das ContextMenu direkt zuweist.
    Fertich.
    Bilder
    • Menu.jpg

      23,46 kB, 358×247, 120 mal angesehen
    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 RodFromGermany!

    Das ist mir bekannt. Ich hatte es nur mit dynamisch erzeugten Controls zu tun, bei denen ich per rechter Maustaste ein im Designer erzeugtes Kontextmenü eines anderen Controls anzeigen wollte. Und es ist mir erst gelungen, das Menü an der Cursorposition darzustellen, indem ich es mit MyDynamicControl.ContextMenu = MyContextMenu an die Controls gebunden habe.
    10000
    Das kannst Du aber auch viel einfacher rauskriegen:
    Füg im Designer ein Control und ein ContextMenu ein, weise dieses jenem zu und sieh in der Datei FormX.Designer.vb nach, wie das vom System gelöst wird.
    Das gilt für alles, was mit dynamisch erstellten Controls zu tun hat. :thumbsup:
    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!
    Ich habe endlich die Lösung für mein Problem gefunden:

    Der ehemalige Code
    Spoiler anzeigen

    VB.NET-Quellcode

    1. AddHandler TableLayoutPanel.MouseMove, AddressOf Tab_MouseMove
    2. AddHandler lblTitle.MouseMove, AddressOf Tab_MouseMove
    3. AddHandler btnClose.MouseMove, AddressOf Tab_MouseMove
    4. AddHandler TableLayoutPanel.MouseLeave, AddressOf Tab_MouseLeave
    5. AddHandler lblTitle.MouseLeave, AddressOf Tab_MouseLeave
    6. AddHandler btnClose.MouseLeave, AddressOf Tab_MouseLeave
    7. Private Sub Tab_MouseMove(ByVal sender as Object, ByVal e As System.EventArgs)
    8. End Sub
    9. Private Sub Tab_MouseLeave(ByVal sender as Object, ByVal e As System.EventArgs)
    10. End Sub
    wird zu:

    VB.NET-Quellcode

    1. Private Sub OnMouseMove(ByVal sender as Object, ByVal e As System.EventArgs) _
    2. Handler TableLayoutPanel.MouseMove, lblTitle.MouseMove, btnClose.MouseMove
    3. MyBase.OnMouseMove(e)
    4. End Sub
    5. Private Sub OnMouseLeave(ByVal sender as Object, ByVal e As System.EventArgs) _
    6. Handler TableLayoutPanel.MouseLeave, lblTitle.MouseLeave, btnClose.MouseLeave
    7. MyBase.OnMouseLeave(e)
    8. End Sub


    Nun können die Move- und Leave-Events als jeweils ein Event des ContainerControls verwaltet werden und müssen zukünftig nicht alle einzeln betrachtet werden.