Button CustomTabControl

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    Button CustomTabControl

    Moin moin :)

    Ich habe mir das TabControl mal etwas umgebaut. Soweit klappt alles wie ich es wollte. Einzig, die "Scroll-Button" des TabControls bekomme ich nicht anders designed. Siehe Bildanhang... sowas von unschööön...
    Vielleicht kann mir dabei jemand helfen :?:

    Hier mal mein Code:

    Spoiler anzeigen

    Das Form: (CustomTabControl auf das Form gezogen)

    VB.NET-Quellcode

    1. Public Class FrmMain
    2. Public Sub New()
    3. InitializeComponent()
    4. ' Das TabControl einfärben
    5. TabControlColorManager.Instance.ApplyColors(CustomTabControl1)
    6. TabControlColorManager.Instance.ApplyColors(CustomTabControl2)
    7. End Sub
    8. End Class


    Die Klasse zum setzen der Farben:

    VB.NET-Quellcode

    1. Public Class TabControlColorManager
    2. Inherits PropertyChange
    3. ' Singleton-Instanz für den zentralen Zugriff auf die Farbanpassungen
    4. Public Shared ReadOnly Property Instance As New TabControlColorManager()
    5. ' Eigenschaften zur Definition der Farbschemata
    6. Public Property TabControlForeColor As Color ' Schriftfarbe des TabControls
    7. Public Property TabControlBackColor As Color ' Hintergrundfarbe des gesamten TabControls
    8. Public Property TabControlBorderColor As Color ' Rahmenfarbe des gesamten TabControls
    9. Public Property TabPagesForeColor As Color ' Schriftfarbe der TabPages
    10. Public Property TabPagesBackColor As Color ' Hintergrundfarbe der TabPages
    11. Public Property TabPageBorderColor As Color ' Rahmenfarbe der aktiven TabPage
    12. Public Property TabControlBordersize As Integer ' Rahmenbreite des TabControl
    13. Public Property TabPageBordersize As Integer ' Rahmenbreite der TabPages
    14. Public Property TabHoverColor As Color ' Die HoverColor der Tabreiter
    15. Private Sub New()
    16. ' Standardfarben definieren
    17. TabControlBackColor = Color.FromArgb(40, 40, 40) ' Hintergrund für das TabControl
    18. TabControlBorderColor = Color.FromArgb(90, 90, 90) ' Rahmen um das TabControl
    19. TabControlBordersize = 1 ' Bordersize des TabControl
    20. TabControlForeColor = Color.SteelBlue ' Schriftfarbe für die Reiter
    21. TabHoverColor = Color.FromArgb(80, 80, 80) ' HoverColor
    22. TabPagesForeColor = Color.Beige ' Schriftfarbe innerhalb der TabPages
    23. TabPagesBackColor = Color.FromArgb(60, 60, 60) ' Hintergrundfarbe der TabPages
    24. ' Optionaler Rahmen um die TabPage (Standart BorderStyle auf None)
    25. TabPageBordersize = 1 ' Bordersize der TabPages
    26. TabPageBorderColor = Color.FromArgb(90, 90, 90)
    27. End Sub
    28. ' Methode zum Anwenden der definierten Farben auf ein TabControl
    29. Public Sub ApplyColors(tabControl As TabControl)
    30. ' Farben für das gesamte TabControl setzen
    31. tabControl.ForeColor = TabControlForeColor
    32. tabControl.BackColor = TabControlBackColor
    33. ' Farben für jede TabPage individuell setzen
    34. For Each page As TabPage In tabControl.TabPages
    35. page.ForeColor = TabPagesForeColor
    36. page.BackColor = TabPagesBackColor
    37. Next
    38. ' TabControl zur Neuzeichnung auffordern
    39. tabControl.Invalidate()
    40. End Sub
    41. End Class


    Das CustomTabControl:

    VB.NET-Quellcode

    1. Public Class CustomTabControl
    2. Inherits TabControl
    3. ' Index des Tabs, über dem die Maus aktuell schwebt
    4. Private hoveredTabIndex As Integer = -1
    5. Public Sub New()
    6. MyBase.New()
    7. Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer, True)
    8. Me.DrawMode = TabDrawMode.OwnerDrawFixed
    9. End Sub
    10. Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
    11. MyBase.OnMouseMove(e)
    12. ' Ermitteln, über welchem Tab die Maus schwebt
    13. Dim newHoveredIndex As Integer = -1
    14. For i As Integer = 0 To Me.TabPages.Count - 1
    15. If Me.GetTabRect(i).Contains(e.Location) Then
    16. newHoveredIndex = i
    17. Exit For
    18. End If
    19. Next
    20. ' Wenn der Hover-Index sich geändert hat, neu zeichnen
    21. If newHoveredIndex <> hoveredTabIndex Then
    22. hoveredTabIndex = newHoveredIndex
    23. Me.Invalidate()
    24. End If
    25. End Sub
    26. Protected Overrides Sub OnMouseLeave(e As EventArgs)
    27. MyBase.OnMouseLeave(e)
    28. ' Hover-Effekt entfernen, wenn die Maus das TabControl verlässt
    29. If hoveredTabIndex <> -1 Then
    30. hoveredTabIndex = -1
    31. Me.Invalidate()
    32. End If
    33. End Sub
    34. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    35. MyBase.OnPaint(e)
    36. ' Hintergrund des gesamten TabControl zeichnen
    37. Dim backColor As Color = TabControlColorManager.Instance.TabControlBackColor
    38. Using backBrush As New SolidBrush(backColor)
    39. e.Graphics.FillRectangle(backBrush, Me.ClientRectangle)
    40. End Using
    41. ' Tab-Reiter und Rahmen zeichnen
    42. For i As Integer = 0 To Me.TabPages.Count - 1
    43. DrawTab(e.Graphics, i)
    44. Next
    45. ' Rahmen des TabControl zeichnen
    46. Using borderPen As New Pen(TabControlColorManager.Instance.TabControlBorderColor, TabControlColorManager.Instance.TabControlBordersize)
    47. Dim rect As Rectangle = Me.ClientRectangle
    48. rect.Width -= 1
    49. rect.Height -= 1
    50. e.Graphics.DrawRectangle(borderPen, rect)
    51. End Using
    52. ' Rahmen um die aktive TabPage zeichnen
    53. If Me.SelectedIndex >= 0 Then
    54. DrawTabPageBorder(e.Graphics)
    55. End If
    56. End Sub
    57. Private Sub DrawTab(g As Graphics, index As Integer)
    58. Dim tabRect As Rectangle = Me.GetTabRect(index)
    59. ' Farben für den Tab-Reiter abrufen
    60. Dim backColor As Color
    61. If index = hoveredTabIndex Then
    62. backColor = TabControlColorManager.Instance.TabHoverColor ' Hover-Farbe verwenden
    63. ElseIf index = Me.SelectedIndex Then
    64. backColor = TabControlColorManager.Instance.TabPagesBackColor ' Aktiver Tab
    65. Else
    66. backColor = TabControlColorManager.Instance.TabControlBackColor ' Standardfarbe
    67. End If
    68. Dim foreColor As Color = If(index = Me.SelectedIndex, TabControlColorManager.Instance.TabPagesForeColor, TabControlColorManager.Instance.TabControlForeColor)
    69. ' Hintergrund des Tabs zeichnen
    70. Using backBrush As New SolidBrush(backColor)
    71. g.FillRectangle(backBrush, tabRect)
    72. End Using
    73. ' Text des Tabs zeichnen
    74. Using textBrush As New SolidBrush(foreColor)
    75. Dim text As String = Me.TabPages(index).Text
    76. Dim sf As New StringFormat With {
    77. .Alignment = StringAlignment.Center,
    78. .LineAlignment = StringAlignment.Center
    79. }
    80. g.DrawString(text, Me.Font, textBrush, tabRect, sf)
    81. End Using
    82. End Sub
    83. ' Methode, die einen Rahmen um die TabPages zeichnet
    84. Private Sub DrawTabPageBorder(g As Graphics)
    85. Dim borderSize As Integer = TabControlColorManager.Instance.TabPageBordersize
    86. If borderSize <= 0 Then Exit Sub
    87. ' Aktive TabPage ermitteln
    88. Dim pageRect As Rectangle = Me.TabPages(Me.SelectedIndex).Bounds
    89. Using borderPen As New Pen(TabControlColorManager.Instance.TabPageBorderColor, borderSize)
    90. g.DrawRectangle(borderPen, New Rectangle(pageRect.Left - 1, pageRect.Top - 1, pageRect.Width + 1, pageRect.Height + 1))
    91. End Using
    92. End Sub
    93. End Class

    Bilder
    • tabcontrol.jpg

      59,95 kB, 462×378, 58 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Ich hatte solch vor Jahren auch mal gemacht. Ich hatte hier gespickt:(Zumindest glaub ich das es das war)
    "Add a custom Scroller to Tabcontrol."
    dotnetrix.co.uk/tabcontrol.htm#tip15


    @Amelie
    Du solltest lieber mal WPF lernen, das schaut nicht nur besser aus, sondern du kannst Designen bis zum geht nicht mehr. Wenn man das erstmal verstanden hat, ist das sogar leichter als in Forms, dann gibst kein halten mehr. :D
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Huhu @Amelie,
    @DTF hat wohl recht. ;)
    Ich habe mein Programm auch mit Forms graphisch komplett gestaltbar hingefummelt.
    Auch ich bin an den Buttons In den TabControls gescheitert und habe dann die TabBar durch eine Auswahl-Datagridview ausgetauscht.
    Für diese Buttons und die Schieberegler in den Datagridviews habe ich trotz langem Suchens keine Möglichkeit gefunden, deren Farben und Stile mit vertretbarem Aufwand selbst definieren zu können.
    Das nächste Projekt, in welchem ich diese graphische Gestaltungsmöglichkeit haben will, werde ich gleich in WPF versuchen und mich nicht mit Forms abquälen.
    @Amelie
    Da wo du mit Strings hantierst um Min/Max/X-Button zurecht zu machen, nimmt man im WPF z.B. Pfade oder was du dir auch vorstellen kannst. Schau mal mit Anhang mit <Path>'s als Button.Content, weil das Vectorbasiert ist, kannste das bis zur unendlichkeit skallieren ohne Verpixelungen zu bekommen, ist genau wie mit den Pfaden in SVGs. Kannst auch die Pfade aus SVG Dateien nehmen. Kommt gut egal ob Windows Skallierung bei 100% oder 300% ist. Auch wie schön sich die ComboBox in die Titlebar einschmiegt. In WPF nur ein wenig XAML. Auch verschiedene Styles einfach zur Laufzeit austauschen. Genauso einfach wie Styles kannst auch die Sprache wechseln, sofern du ResourceDictionary's anlegst.
    Bilder
    • Unbenannt.jpg

      10,5 kB, 560×144, 44 mal angesehen
    • Unbenannt1.jpg

      12,41 kB, 483×66, 45 mal angesehen
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    @DTF

    Moin moin

    Ich verstehe, warum so viele von WPF begeistert sind – die Möglichkeiten, vor allem im Vergleich zu WinForms, sind wirklich beeindruckend. Trotzdem ist mir der Einstieg in WPF aktuell einfach zu viel. Für meine kleineren Anwendungen ist der Aufwand, mich mit all den Konzepten, der Trennung von Code und Design sowie den verschiedenen Sprachen zu beschäftigen, einfach zu hoch. Dazu bin ich noch viel zu sehr "Anfänger(in)" :)

    Auch das MVVM-Pattern, das oft in Verbindung mit WPF genutzt wird, ist sicher eine clevere Sache. Aber für meine Zwecke finde ich es meistens überdimensioniert.
    Bei meinen Projekten habe ich festgestellt, dass ein einfaches "Mini-MVC-Pattern" völlig ausreicht, um die Logik sauber von der Benutzeroberfläche zu trennen.

    Natürlich stoße ich mit WinForms manchmal an Grenzen, gerade was das Design angeht. Aber damit kann ich leben – zumindest so lange, bis ich wirklich mehr aus meinen Anwendungen herausholen will.
    Dann werde ich mich wohl oder übel auch näher mit WPF und seinen Möglichkeiten beschäftigen oder beschäftigen müssen.


    @VB1963
    ​Sieht doch eh so standardmäßig aus? - oder verstehe ich dich da falsch...

    Ich meinte die beiden "dunklen Buttons mit den blauen Pfeilen". So hätte ich es gerne.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Aber für meine Zwecke finde ich es meistens überdimensioniert.


    Es gibt keinen Zwang MVVM anzuwenden. Kannst auch die RoutedEvents nutzen, das funktioniert auch wie in Forms. Da hast du den Code dann auch in der Klasse vom Window selbst anstatt in einem ViewModel.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @DTF

    Ja stimmt zwang besteht nicht, aber wenn man schon das ganze WPF nutzt dann auch mit MVVM...
    Habe mir mal das mit dem "RoutedEvents" grob angesehen.
    Mein Fazit: Für meine Sachen einfach zu überdimensioniert.

    Habe in meinen Windows Form ( net4.8 / net.6 / 7 ) Projekten, schon mit "MCV / MVVM" soweit wie es möglich ist das umzusetzen, um GUI und Logik zu trennen gearbeitet. Ist nicht immer ganz einfach aber für mich wesentlich einfacher als dieses "WPF-Durcheinander" ^^
    Vielleicht hätte ich gleich mit WPF das coden lernen sollen .... :?: :?:
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Vielleicht hätte ich gleich mit WPF das coden lernen sollen ....


    Wäre zwar eine Option gewesen, aber Forms ist anfängerfreundlicher, weil man nicht gleich zweierlei lernen muss. VB/C# und XAML. Ich hab mich damals für Forms entschieden, weil die Controls default besser aussahen, ich keine Lust hatte auch XAML zu lernen. IMO ein Fehler. Beides sind brauchbare Technologien, aber ob WPF wirklich noch Zukunft hat? WPF wird nicht mehr weiter entwickelt, aber WinUI scheint viel dran gemacht zu werden, da könnte WinUI sogar die bessere Option sein. Aber da fehlt noch die Designer-Preview, wenn man live sehen will wenn man XAML schreibt, muss man das Programm starten, dann wird das live übernommen und angezeigt.

    Aber andere Pattern zu lernen ist nicht falsch, finde ich sogar wichtig. Wichtig dabei ist nur, man muss Vor und Nachteile kennen, damit man diese richtig einsetzen kann. Also wenn, dann auch mit Nachteilen beschäftigen, und ab und zu trotzdem mal was verbauen, dann lernt man das schon :D
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    @DTF

    Hab mir nun mal das "WinUI" angesehen....

    ​Aber da fehlt noch die Designer-Preview

    Das klingt für mich erstmal nach einem Rückschritt in die Zeiten wo es noch keine "Visual-Unterstützung" zum coden gab.
    Zudem ist WinUI wohl primär auf C# und mobile Geräte ausgelegt?

    ​Aber andere Pattern zu lernen ist nicht falsch

    Das stimmt. Werde mich wohl oder übel in den kommenden Jahren mehr mit C# und WinUI beschäftigen müssen.

    Aber noch reicht mir .Net 4.8 / .Net 8 und Windows Forms für meine Sachen .... :D
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Das klingt für mich erstmal nach einem Rückschritt in die Zeiten wo es noch keine "Visual-Unterstützung" zum coden gab.


    Man hat ja eine Ansicht, beim debuggen muss man dann halt den XAML editieren. Was du in der IDE machst, wird live im Programm übernommen(Nur XAML). Fügst du einen Button hinzu im XAML während das Programm läuft und das Studio dranhängt, wird das im Programm übernommen.

    Amelie schrieb:

    Zudem ist WinUI wohl primär auf C# und mobile Geräte ausgelegt?


    Nein und nein. WinUI kannste neben C# auch mit C++ verwenden. VB wird sicher auch gehen, aber es sind keine Projekttemplates im Studio vorhanden. Müsste man sich eins machen und testen.

    WinUI ist eine reine UI-Bibliothek für Windows(10 und 11), gedacht um MSIX-Packete zu packen für den Store. Aber man kann das auch ungepackt nutzen, so das man wie gewohnt die EXE startet. Um das zu können MUSS man aber die Doku lesen, man muss dazu nämlich die Projektdatei editieren.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()