Colored Menues

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

    Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

      Colored Menues

      Moin moin :)

      Ich habe meinen "Menu-Styler", der in einigen meiner Programme verwendet wird, überarbeitet und erweitert, um ihn vielseitiger einsetzbar zu machen. Der neue Ansatz betrifft sowohl das MainMenuStrip als auch das ContextMenuStrip.
      Der Code in der Windows-Form-Class ist dabei minimal gehalten, um eine einfache Integration zu ermöglichen. Die Farbanpassungen werden zentral in der MenuStylingConfig-Klasse vorgenommen, sodass Änderungen an den Menüfarben problemlos und an einer Stelle vorgenommen werden können.

      Zusätzlich habe ich eine ContextMenuController-Klasse entwickelt, die für die Verwaltung und Verarbeitung der Kontextmenüoptionen zuständig ist. Diese Klasse kann flexibel auf die Anforderungen der Anwendung angepasst werden und bietet auch die Möglichkeit, ähnliche Funktionen für das MainMenu zu integrieren. So wird der gesamte Menü-Handling-Prozess vereinfacht und gleichzeitig die Flexibilität erhöht, verschiedene Menüs und deren Eigenschaften auf konsistente Weise zu steuern.

      Kleine Code-Auszüge:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Class FrmMain
      2. Public Sub New()
      3. InitializeComponent()
      4. MainMenuStyler.Instance.ApplyStyleToAllMenuStrips(Me)
      5. ContextMenuStyler.Instance.ApplyStyleToContextMenu(ContextMenuStrip1)
      6. ' Event-Handler für Menüoptionen hinzufügen
      7. AddHandler ContexMenuController.Instance.MenuOptionSelected, AddressOf OnMenuOptionSelected
      8. ' Gemeinsamen Click-Handler für alle Menüeinträge zuweisen
      9. ContexMenuController.Instance.AssignHandlersToMenuItems(ContextMenuStrip1.Items)
      10. End Sub
      11. ' Button zum testen des Context-Menu
      12. Private Sub BtnContextMenu_Click(sender As Object, e As EventArgs) Handles BtnContextMenu.Click
      13. Dim button As Button = DirectCast(sender, Button)
      14. Dim buttonLocation As Point = button.PointToScreen(New Point(0, button.Height))
      15. ' ContextMenuStrip anzeigen
      16. ContextMenuStrip1.Show(buttonLocation)
      17. End Sub
      18. ' Callback für Menüoptionen
      19. Private Sub OnMenuOptionSelected(options As ContexMenuController.MenuOptions)
      20. ContexMenuController.Instance.ProcessMenuOption(options)
      21. End Sub
      22. End Class


      VB.NET-Quellcode

      1. Public Class MenuStylingConfig
      2. ' Singleton-Instanz
      3. Public Shared ReadOnly Property Instance As New MenuStylingConfig()
      4. ' Allgemeine Farben
      5. Public Property ForeColor As Color = Color.DeepSkyBlue
      6. Public Property BackgroundColor As Color = Color.FromArgb(50, 50, 50)
      7. Public Property HoverColor As Color = Color.FromArgb(100, 100, 100)
      8. Public Property ItemBackgroundColor As Color = Color.FromArgb(60, 60, 60)
      9. Public Property BorderColor As Color = Color.Transparent
      10. Private Sub New()
      11. End Sub
      12. End Class


      VB.NET-Quellcode

      1. Public Class ContexMenuController
      2. Public Shared ReadOnly Property Instance As New ContexMenuController()
      3. Public Event MenuOptionSelected As Action(Of MenuOptions)
      4. ' Enum für Menüoptionen
      5. Public Enum MenuOptions
      6. None
      7. Option1
      8. Option2
      9. Option3
      10. Option4
      11. End Enum
      12. ' Methode zur Verarbeitung der Optionen
      13. Public Sub ProcessMenuOption(options As MenuOptions)
      14. Select Case options
      15. Case MenuOptions.Option1
      16. MessageBox.Show("Option 1 ausgewählt")
      17. Case MenuOptions.Option2
      18. MessageBox.Show("Option 2 ausgewählt")
      19. Case MenuOptions.Option3
      20. MessageBox.Show("Option 3 ausgewählt")
      21. Case MenuOptions.Option4
      22. MessageBox.Show("Option 4 ausgewählt")
      23. Case Else
      24. MessageBox.Show("Keine gültige Option ausgewählt")
      25. End Select
      26. End Sub
      27. ' Gemeinsamer Click-Handler für alle Menüeinträge
      28. Private Sub ContextMenuItem_Click(sender As Object, e As EventArgs)
      29. Dim menuItem As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
      30. ' Dictionary für die Zuordnung von Namen zu Optionen
      31. Dim menuOptionMapping As New Dictionary(Of String, MenuOptions) From {
      32. {"ContextItem_1", MenuOptions.Option1},
      33. {"SubItem_1_1", MenuOptions.Option2},
      34. {"SubItem_1_2", MenuOptions.Option3},
      35. {"ContextItem_2", MenuOptions.Option4}
      36. }
      37. ' Überprüfen, ob der Name des Items im Mapping vorhanden ist
      38. If menuOptionMapping.ContainsKey(menuItem.Name) Then
      39. RaiseEvent MenuOptionSelected(menuOptionMapping(menuItem.Name)) ' Verwendung von RaiseEvent
      40. Else
      41. RaiseEvent MenuOptionSelected(MenuOptions.None) ' Wenn kein passender Name gefunden wurde
      42. End If
      43. End Sub
      44. ' Methode zum Zuweisen des Click-Handlers für alle Menüeinträge
      45. Public Sub AssignHandlersToMenuItems(items As ToolStripItemCollection)
      46. For Each item As ToolStripItem In items
      47. If TypeOf item Is ToolStripMenuItem Then
      48. Dim menuItem As ToolStripMenuItem = DirectCast(item, ToolStripMenuItem)
      49. ' Zuweisen des gemeinsamen Click-Handlers
      50. AddHandler menuItem.Click, AddressOf ContextMenuItem_Click
      51. ' Rekursive Zuweisung für Untermenüs
      52. If menuItem.HasDropDownItems Then
      53. AssignHandlersToMenuItems(menuItem.DropDownItems)
      54. End If
      55. End If
      56. Next
      57. End Sub
      58. End Class



      Das ganze bereinigte Projekt in der angehängten Zip-Datei.

      Kommentare, Verbesserungen und Feedbacks lese ich gerne. :rolleyes:
      Ansonsten allen einen schönen "Heilig Abend" :rolleyes:

      Verschoben. ~Thunderbolt
      Dateien
      • MenuStyler.zip

        (18,74 kB, 39 mal heruntergeladen, zuletzt: )
      Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

      @Amelie Dein ContextMenuStyler-Singleton ist nicht ganz korrekt implementiert:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. ' Singleton-Instanz
      2. Public Shared ReadOnly Property GetInstance As ContextMenuStyler
      3. Get
      4. If Instance Is Nothing Then
      5. Instance = New ContextMenuStyler()
      6. End If
      7. Return Instance
      8. End Get
      9. End Property
      10. Private Shared Instance As ContextMenuStyler
      11. ' privater Konstruktor
      12. Private Sub New()
      13. End Sub

      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!
      Moin moin @RodFromGermany

      Also in .Net 4.8 FW funktioniert mein ( kompaktes ) Singleton, jedoch weiß ich, das es unter .Net 7 / 8 wohl eher deine Implementierung benötigt.
      Warum das so ist hab ich noch nicht so richtig verstanden.

      Ich mache eher weniger in .Net 7 / 8 weil das Studio (VS22) damit doch sehr langsam wird und ich immer wieder auf Probleme stoße. :(

      PS:
      So ganz gefällt mir eh die "ContexMenuController-Class" noch nicht. Hast du vielleicht Ideen das anders zu gestalten? :)
      Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
      Schönen ersten Feiertag Euch allen.

      Ich habe die ContexMenuController-Class nochmal umgebaut und eine weitere ContexMenuHandler-Class (für RelayCommand optional nutzbar) hinzugefügt.
      Rest vom Code ist unverändert...

      Mit der Nutzung der ContexMenuHandler-Class kann man die Trennungen noch weiter ausbauen, aber wohl für kleine Projekte "überdimensioniert"??

      Spoiler anzeigen

      Die neue ContexMenuController

      VB.NET-Quellcode

      1. Public Class ContexMenuController
      2. Public Shared ReadOnly Property Instance As ContexMenuController
      3. Get
      4. If _instance Is Nothing Then
      5. _instance = New ContexMenuController()
      6. End If
      7. Return _instance
      8. End Get
      9. End Property
      10. Private Shared _instance As ContexMenuController
      11. Public Event MenuOptionSelected As Action(Of MenuOptions)
      12. ' Enum für Menüoptionen
      13. Public Enum MenuOptions
      14. None
      15. Option1
      16. Option2
      17. Option3
      18. Option4
      19. End Enum
      20. ' Dictionary für die Zuordnung von Menüeinträgen zu Menüoptionen
      21. Private ReadOnly menuOptionMapping As New Dictionary(Of String, MenuOptions) From {
      22. {"ContextItem_1", MenuOptions.Option1},
      23. {"SubItem_1_1", MenuOptions.Option2},
      24. {"SubItem_1_2", MenuOptions.Option3},
      25. {"ContextItem_2", MenuOptions.Option4}
      26. }
      27. ' Methode zur Verarbeitung der Optionen
      28. Public Sub ProcessMenuOption(options As MenuOptions)
      29. HandleMenuOption(options)
      30. End Sub
      31. ' Gemeinsame Methode für alle Menüoptionen
      32. Private Sub HandleMenuOption(options As MenuOptions)
      33. Select Case options
      34. Case MenuOptions.Option1
      35. ' Optional mit RelayCommand
      36. ContexMenuHandler.Instance.ExecuteOption1.Execute(Nothing)
      37. Case MenuOptions.Option2
      38. ' Ohne RelayCommand
      39. SubOption_2()
      40. Case MenuOptions.Option3
      41. SubOption_3()
      42. Case MenuOptions.Option4
      43. SubOption_4()
      44. Case Else
      45. MessageBox.Show("Keine gültige Option ausgewählt")
      46. End Select
      47. End Sub
      48. ' Gemeinsamer Click-Handler für alle Menüeinträge
      49. Private Sub ContextMenuItem_Click(sender As Object, e As EventArgs)
      50. Dim menuItem As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
      51. ' Menüeintrag-Namen zu MenuOptions umwandeln
      52. If menuOptionMapping.ContainsKey(menuItem.Name) Then
      53. Dim selectedOption As MenuOptions = menuOptionMapping(menuItem.Name)
      54. HandleMenuOption(selectedOption)
      55. Else
      56. MessageBox.Show("Unbekannter Menüeintrag")
      57. End If
      58. End Sub
      59. ' Methode zum Zuweisen des Click-Handlers für alle Menüeinträge
      60. Public Sub AssignHandlersToMenuItems(items As ToolStripItemCollection)
      61. For Each item As ToolStripItem In items
      62. If TypeOf item Is ToolStripMenuItem Then
      63. Dim menuItem As ToolStripMenuItem = DirectCast(item, ToolStripMenuItem)
      64. ' Zuweisen des gemeinsamen Click-Handlers
      65. AddHandler menuItem.Click, AddressOf ContextMenuItem_Click
      66. ' Rekursive Zuweisung für Untermenüs
      67. If menuItem.HasDropDownItems Then
      68. AssignHandlersToMenuItems(menuItem.DropDownItems)
      69. End If
      70. End If
      71. Next
      72. End Sub
      73. ' Methoden ohne RealyCommand Nutzung
      74. Private Sub SubOption_2()
      75. MessageBox.Show("Option 2 ausgewählt")
      76. End Sub
      77. Private Sub SubOption_3()
      78. MessageBox.Show("Option 3 ausgewählt")
      79. End Sub
      80. Private Sub SubOption_4()
      81. MessageBox.Show("Option 4 ausgewählt")
      82. End Sub
      83. End Class


      Die neue ContexMenuHandler ( Optional mit RelayCommand )

      VB.NET-Quellcode

      1. Public Class ContexMenuHandler
      2. Public Shared ReadOnly Property Instance As ContexMenuHandler
      3. Get
      4. If _instance Is Nothing Then
      5. _instance = New ContexMenuHandler
      6. End If
      7. Return _instance
      8. End Get
      9. End Property
      10. Private Shared _instance As ContexMenuHandler
      11. Public Property ExecuteOption1 As New RelayCommand(AddressOf ActionOption1)
      12. ' Methoden für jede Option
      13. Private Sub ActionOption1()
      14. MessageBox.Show("Option 1 ausgewählt")
      15. End Sub
      16. End Class

      Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

      RodFromGermany schrieb:

      @Amelie Dein ContextMenuStyler-Singleton ist nicht ganz korrekt implementiert
      hmm - mir sieht das ganz richtig aus, was Amelie ursprünglich gemacht hat.
      Und auch hübscher: nur eine Zeile - kein Brimborium.

      Deine Variante dagegen ist ziemlich OldSchool, als es die Auto-Properties noch nicht gab.