none
tabcontrol RRS feed

  • Question

  • hi

    i found this class  for tabcontrol

    i want to add close button and image

    Imports System.Drawing.Drawing2D
    Imports System.Drawing.Text
    
    Class FirefoxSubTabControl
        Inherits TabControl
        Public ReadOnly Property GlobalFont(ByVal B As FontStyle, ByVal S As Integer) As Font
            Get
                Return New Font("Segoe UI", S, B)
            End Get
        End Property
        Public Sub CenterStringTab(ByVal G As Graphics, ByVal text As String, ByVal font As Font, ByVal brush As Brush, ByVal rect As Rectangle, Optional ByVal shadow As Boolean = False, Optional ByVal yOffset As Integer = 0)
    
            Dim textSize As SizeF = G.MeasureString(text, font)
            Dim textX As Integer = rect.X + (rect.Width / 2) - (textSize.Width / 2)
            Dim textY As Integer = rect.Y + (rect.Height / 2) - (textSize.Height / 2) + yOffset
    
            If shadow Then G.DrawString(text, font, Brushes.Black, textX + 1, textY + 1)
            G.DrawString(text, font, brush, textX, textY + 1)
    
        End Sub
        Public Function GreyColor(ByVal G As UInteger) As Color
            Return Color.FromArgb(G, G, G)
        End Function
    #Region " Private "
        Private G As Graphics
        Private TabRect As Rectangle
    #End Region
    
    #Region " Control "
    
        Sub New()
            DoubleBuffered = True
            Alignment = TabAlignment.Top
        End Sub
    
        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
            SetStyle(ControlStyles.UserPaint, True)
            ItemSize = New Size(100, 40)
            SizeMode = TabSizeMode.Fixed
        End Sub
    
        Protected Overrides Sub OnControlAdded(ByVal e As ControlEventArgs)
            MyBase.OnControlAdded(e)
            Try
                For i As Integer = 0 To TabPages.Count - 1
                    TabPages(i).BackColor = Color.White
                    TabPages(i).ForeColor = Color.FromArgb(66, 79, 90)
                    TabPages(i).Font = GlobalFont(FontStyle.Regular, 10)
                Next
            Catch
            End Try
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    
            G = e.Graphics
            G.SmoothingMode = SmoothingMode.HighQuality
            G.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    
            MyBase.OnPaint(e)
    
            G.Clear(Parent.BackColor)
    
            For i As Integer = 0 To TabPages.Count - 1
    
                TabRect = GetTabRect(i)
    
                If GetTabRect(i).Contains(Me.PointToClient(Cursor.Position)) And Not SelectedIndex = i Then
    
                    Using B As New SolidBrush(GreyColor(240))
                        G.FillRectangle(B, New Rectangle(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2, GetTabRect(i).Width, GetTabRect(i).Height + 1))
                    End Using
    
                ElseIf SelectedIndex = i Then
    
                    Using B As New SolidBrush(GreyColor(240))
                        G.FillRectangle(B, New Rectangle(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2, GetTabRect(i).Width, GetTabRect(i).Height + 1))
                    End Using
    
                    Using P As New Pen(Color.FromArgb(255, 149, 0), 4)
                        G.DrawLine(P, New Point(TabRect.X - 2, TabRect.Y + ItemSize.Height - 2), New Point(TabRect.X + TabRect.Width - 2, TabRect.Y + ItemSize.Height - 2))
                    End Using
    
                ElseIf Not SelectedIndex = i Then
                    G.FillRectangle(Brushes.White, GetTabRect(i))
                End If
    
                Using B As New SolidBrush(Color.FromArgb(56, 69, 80))
                    CenterStringTab(G, TabPages(i).Text, GlobalFont(FontStyle.Regular, 10), B, GetTabRect(i))
                End Using
    
            Next
    
            Using P As New Pen(GreyColor(200))
                G.DrawLine(P, New Point(0, ItemSize.Height + 2), New Point(Width, ItemSize.Height + 2))
            End Using
    
        End Sub
    
    
    
    #End Region
    
    End Class

    Saturday, January 19, 2019 5:31 PM

Answers

  • Here is an example using the original including right to left.  :)

    Imports System.Drawing.Drawing2D
    Imports System.Drawing.Text
    
    Public Class Form2
        Private WithEvents Tab1 As New FirefoxSubTabControlEX With {.Parent = Me,
            .Location = New Point(10, 10), .Size = New Size(450, 250)}
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
    
            Tab1.TabPages.Add("Page One")
            Tab1.TabPages.Add("Page Two")
            Tab1.TabPages.Add("Page Three")
            Tab1.ItemSize = New Size(140, 30)
            Tab1.ButtonSize = New Size(18, 18)
            Tab1.Font = New Font("Segoe UI", 10, FontStyle.Regular)
    
            Tab1.RightToLeft = RightToLeft.Yes
            Tab1.RightToLeftLayout = True
    
            'define your own image path
            Tab1.TabIcon = New Bitmap("c:\bitmaps\crlogo16b.ico")
    
        End Sub
    
        Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Tab1.Width = ClientSize.Width - (Tab1.Left * 2)
            Tab1.Height = ClientSize.Height - (Tab1.Top * 2)
            Tab1.Invalidate()
        End Sub
    End Class
    
    Class FirefoxSubTabControlEX
        Inherits TabControl
        Public TabIcon As Bitmap = Nothing
        Public ButtonSize As Size = New Size(16, 16)
        Private MouseState As Integer
    
        Sub New()
            DoubleBuffered = True
            Alignment = TabAlignment.Top
        End Sub
    
        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
            SetStyle(ControlStyles.UserPaint, True)
            SizeMode = TabSizeMode.Fixed
        End Sub
    
        Protected Overrides Sub OnControlAdded(ByVal e As ControlEventArgs)
            MyBase.OnControlAdded(e)
            Try
                For i As Integer = 0 To TabPages.Count - 1
                    TabPages(i).BackColor = Color.White
                    TabPages(i).ForeColor = Color.FromArgb(66, 79, 90)
                    TabPages(i).Font = Font
                Next
            Catch
            End Try
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            MyBase.OnPaint(e)
    
            With e.Graphics
                .SmoothingMode = SmoothingMode.HighQuality
                .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
                .Clear(Parent.BackColor)
    
                Using brText As New SolidBrush(Color.FromArgb(56, 69, 80)),
                    brGray As New SolidBrush(Color.FromArgb(255, 240, 240, 240)),
                    brHighlight As New SolidBrush(Color.FromArgb(255, 149, 0)),
                    pGray As New Pen(Color.FromArgb(255, 200, 200, 200)),
                    pHighlight As New Pen(Color.FromArgb(255, 149, 0), 4)
                    Dim TabRect As Rectangle
    
                    For i As Integer = 0 To TabPages.Count - 1
    
                        TabRect = GetTabRect(i)
    
                        If TabRect.Contains(Me.PointToClient(Cursor.Position)) And Not SelectedIndex = i Then
                            'mouse highlight background
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
    
                        ElseIf SelectedIndex = i Then
                            'draw background for selected tab
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
                            'highlight
                            .DrawLine(pHighlight, New Point(TabRect.X - 2, TabRect.Y + ItemSize.Height - 2), New Point(TabRect.X + TabRect.Width - 2, TabRect.Y + ItemSize.Height - 2))
    
                            'draw the button
                            Dim bRect As New Rectangle(-5 + TabRect.X + TabRect.Width - ButtonSize.Width,
                                           CInt(TabRect.Y + (TabRect.Height / 2) - (ButtonSize.Height / 2)),
                                           ButtonSize.Width, ButtonSize.Height)
                            .DrawRectangle(pGray, bRect)
    
                            Select Case MouseState  'color by mouse state
                                Case 1  'mousedown
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), Brushes.Gray, bRect.X + 2, bRect.Y)
                                Case 2  'mousemove
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brHighlight, bRect.X + 2, bRect.Y)
                                Case Else
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brText, bRect.X + 2, bRect.Y)
                            End Select
                        Else
                            .FillRectangle(Brushes.White, TabRect)
                        End If
    
                        'draw the text
                        Dim textSize As SizeF = .MeasureString(TabPages(i).Text, Font)
                        Dim textX As Integer = CInt(TabRect.X + (TabRect.Width / 2) - (textSize.Width / 2))
                        Dim textY As Integer = CInt(TabRect.Y + (TabRect.Height / 2) - (textSize.Height / 2))
                        If TabIcon IsNot Nothing Then textX += CInt(TabIcon.Width / 2)
    
                        .DrawString(TabPages(i).Text, Font, brText, textX, textY + 1)
    
                        'draw the icon
                        .DrawImage(TabIcon, New Rectangle(TabRect.X + 5, CInt(TabRect.Y + (0.2 * TabRect.Height)),
                                        CInt(0.6 * TabRect.Height), CInt(0.6 * TabRect.Height)))
                    Next
    
                    'bottom line 
                    .DrawLine(pGray, New Point(0, ItemSize.Height + 2), New Point(Width, ItemSize.Height + 2))
                End Using
            End With
        End Sub
    
        Private Sub Tab_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
            If SelectedIndex > -1 Then
                MouseState = 1
            Else
                MouseState = 0
            End If
            Invalidate()
        End Sub
    
        Private Sub Tab_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
            If SelectedIndex > -1 Then
                Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
                If tabTextArea.Contains(e.Location) Then
                    If e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                        Cursor = Cursors.Hand
                        If MouseState = 0 Then MouseState = 2
                    Else
                        Cursor = Cursors.Default
                        MouseState = 0
                    End If
                    Invalidate()
                Else
                    Cursor = Cursors.Default
                    MouseState = 0
                End If
            End If
        End Sub
    
        Private Sub Tab_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
            Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
    
            If MouseState = 1 AndAlso e.Button = MouseButtons.Left AndAlso e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                TabPages.Remove(TabPages(SelectedIndex))
            End If
            MouseState = 0
        End Sub
    
        Private Sub Tab_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
            MouseState = 0
        End Sub
    
    End Class
    

    • Marked as answer by ahmeddc Sunday, January 20, 2019 11:47 AM
    Sunday, January 20, 2019 1:10 AM
  • Thought I would bring this one up two even though it is not free from Telerik which has just about any option you would want. below I added images, a close button and a pin along with changing the theme. To keep this from being an endorsement I'm not including a link or cost, this is purely informational.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by ahmeddc Sunday, January 20, 2019 11:47 AM
    Saturday, January 19, 2019 9:01 PM
    Moderator

All replies

  • Here is one to try which I didn't write, original source. Does not do the image so you may not want this.

    Option Strict On
    Imports System.ComponentModel
    
    <ToolboxBitmap(GetType(System.Windows.Forms.TabControl))>
    Public Class TabControlEx
        Inherits TabControl
    
        Private Declare Auto Function SetParent Lib "user32" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
        Protected CloseButtonCollection As New Dictionary(Of Button, TabPage)
        Private _ShowCloseButtonOnTabs As Boolean = True
    
        <Browsable(True), DefaultValue(True), Category("Behavior"), Description("Indicates whether a close button should be shown on each TabPage")>
        Public Property ShowCloseButtonOnTabs() As Boolean
            Get
                Return _ShowCloseButtonOnTabs
            End Get
            Set(ByVal value As Boolean)
                _ShowCloseButtonOnTabs = value
                For Each btn In CloseButtonCollection.Keys
                    btn.Visible = _ShowCloseButtonOnTabs
                Next
                RePositionCloseButtons()
            End Set
        End Property
    
        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
    
            For Each item In CloseButtonCollection
    
                item.Value.Text = item.Value.Text.Trim & Space(8)
    
            Next
    
    
            RePositionCloseButtons()
        End Sub
    
        Protected Overrides Sub OnControlAdded(ByVal e As System.Windows.Forms.ControlEventArgs)
            MyBase.OnControlAdded(e)
            Dim tp As TabPage = DirectCast(e.Control, TabPage)
            Dim rect As Rectangle = Me.GetTabRect(Me.TabPages.IndexOf(tp))
            Dim btn As Button = AddCloseButton(tp)
            btn.Size = New Size(rect.Height - 1, rect.Height - 1)
            btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
            SetParent(btn.Handle, Me.Handle)
            AddHandler btn.Click, AddressOf OnCloseButtonClick
            CloseButtonCollection.Add(btn, tp)
        End Sub
    
        Protected Overrides Sub OnControlRemoved(ByVal e As System.Windows.Forms.ControlEventArgs)
            Dim btn As Button = CloseButtonOfTabPage(DirectCast(e.Control, TabPage))
            RemoveHandler btn.Click, AddressOf OnCloseButtonClick
            CloseButtonCollection.Remove(btn)
            SetParent(btn.Handle, Nothing)
            btn.Dispose()
            MyBase.OnControlRemoved(e)
        End Sub
    
        Protected Overrides Sub OnLayout(ByVal levent As System.Windows.Forms.LayoutEventArgs)
            MyBase.OnLayout(levent)
            RePositionCloseButtons()
        End Sub
    
        Public Event CloseButtonClick As CancelEventHandler
        Protected Overridable Sub OnCloseButtonClick(ByVal sender As Object, ByVal e As EventArgs)
            If Not DesignMode Then
                Dim btn As Button = DirectCast(sender, Button)
                Dim tp As TabPage = CloseButtonCollection(btn)
                Dim ee As New CancelEventArgs
                RaiseEvent CloseButtonClick(sender, ee)
                If Not ee.Cancel Then
                    Me.TabPages.Remove(tp)
                    RePositionCloseButtons()
                End If
            End If
        End Sub
    
        Protected Overridable Function AddCloseButton(ByVal tp As TabPage) As Button
            Dim closeButton As New Button
            With closeButton
                '' TODO: Give a good visual appearance to the Close button, maybe by assigning images etc.
                ''       Here I have not used images to keep things simple.
                .Text = "X"
                .FlatStyle = FlatStyle.Flat
                .BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
                .ForeColor = Color.White
                .Font = New Font("Microsoft Sans Serif", 6, FontStyle.Bold)
            End With
            Return closeButton
        End Function
    
        Public Sub RePositionCloseButtons()
            For Each item In CloseButtonCollection
                RePositionCloseButtons(item.Value)
            Next
        End Sub
    
        Public Sub RePositionCloseButtons(ByVal tp As TabPage)
            Dim btn As Button = CloseButtonOfTabPage(tp)
            If btn IsNot Nothing Then
                Dim tpIndex As Integer = Me.TabPages.IndexOf(tp)
                If tpIndex >= 0 Then
                    Dim rect As Rectangle = Me.GetTabRect(tpIndex)
                    If Me.SelectedTab Is tp Then
                        btn.BackColor = Color.Red
                        btn.Size = New Size(rect.Height - 1, rect.Height - 1)
                        btn.Location = New Point(rect.X + rect.Width - rect.Height, rect.Y + 1)
                    Else
                        btn.BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
                        btn.Size = New Size(rect.Height - 3, rect.Height - 3)
                        btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
                    End If
                    btn.Visible = ShowCloseButtonOnTabs
                    btn.BringToFront()
                End If
            End If
        End Sub
    
        Protected Function CloseButtonOfTabPage(ByVal tp As TabPage) As Button
            Return (From item In CloseButtonCollection Where item.Value Is tp Select item.Key).FirstOrDefault
        End Function
    End Class

    Permit cancel close of current tab

    Public Class Form1
        Private Sub TabControlEx1_CloseButtonClick(
            sender As Object,
            e As ComponentModel.CancelEventArgs) Handles TabControlEx1.CloseButtonClick
    
            If Not My.Dialogs.Question($"Close {TabControlEx1.SelectedTab.Text.TrimEnd()} tab?") Then
                e.Cancel = True
            End If
        End Sub
    End Class

    Custom My.Namespace dialog for above (optional)

    Namespace My
        <ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)>
        Partial Friend Class Dialogs
            Public Function Question(message As String) As Boolean
                Return (MessageBox.Show(message, My.Application.Info.Title, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = MsgBoxResult.Yes)
            End Function
            Public Function Question(message As String, title As String) As Boolean
                Return (MessageBox.Show(message, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = MsgBoxResult.Yes)
            End Function
        End Class
        <HideModuleName()>
        Friend Module KarenPayneDialogs
            Private instance As New ThreadSafeObjectProvider(Of Dialogs)
            ReadOnly Property Dialogs() As Dialogs
                Get
                    Return instance.GetInstance()
                End Get
            End Property
        End Module
    End Namespace


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites



    Saturday, January 19, 2019 8:28 PM
    Moderator
  • Thought I would bring this one up two even though it is not free from Telerik which has just about any option you would want. below I added images, a close button and a pin along with changing the theme. To keep this from being an endorsement I'm not including a link or cost, this is purely informational.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by ahmeddc Sunday, January 20, 2019 11:47 AM
    Saturday, January 19, 2019 9:01 PM
    Moderator
  • Here is an example using the original including right to left.  :)

    Imports System.Drawing.Drawing2D
    Imports System.Drawing.Text
    
    Public Class Form2
        Private WithEvents Tab1 As New FirefoxSubTabControlEX With {.Parent = Me,
            .Location = New Point(10, 10), .Size = New Size(450, 250)}
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
    
            Tab1.TabPages.Add("Page One")
            Tab1.TabPages.Add("Page Two")
            Tab1.TabPages.Add("Page Three")
            Tab1.ItemSize = New Size(140, 30)
            Tab1.ButtonSize = New Size(18, 18)
            Tab1.Font = New Font("Segoe UI", 10, FontStyle.Regular)
    
            Tab1.RightToLeft = RightToLeft.Yes
            Tab1.RightToLeftLayout = True
    
            'define your own image path
            Tab1.TabIcon = New Bitmap("c:\bitmaps\crlogo16b.ico")
    
        End Sub
    
        Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Tab1.Width = ClientSize.Width - (Tab1.Left * 2)
            Tab1.Height = ClientSize.Height - (Tab1.Top * 2)
            Tab1.Invalidate()
        End Sub
    End Class
    
    Class FirefoxSubTabControlEX
        Inherits TabControl
        Public TabIcon As Bitmap = Nothing
        Public ButtonSize As Size = New Size(16, 16)
        Private MouseState As Integer
    
        Sub New()
            DoubleBuffered = True
            Alignment = TabAlignment.Top
        End Sub
    
        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
            SetStyle(ControlStyles.UserPaint, True)
            SizeMode = TabSizeMode.Fixed
        End Sub
    
        Protected Overrides Sub OnControlAdded(ByVal e As ControlEventArgs)
            MyBase.OnControlAdded(e)
            Try
                For i As Integer = 0 To TabPages.Count - 1
                    TabPages(i).BackColor = Color.White
                    TabPages(i).ForeColor = Color.FromArgb(66, 79, 90)
                    TabPages(i).Font = Font
                Next
            Catch
            End Try
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            MyBase.OnPaint(e)
    
            With e.Graphics
                .SmoothingMode = SmoothingMode.HighQuality
                .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
                .Clear(Parent.BackColor)
    
                Using brText As New SolidBrush(Color.FromArgb(56, 69, 80)),
                    brGray As New SolidBrush(Color.FromArgb(255, 240, 240, 240)),
                    brHighlight As New SolidBrush(Color.FromArgb(255, 149, 0)),
                    pGray As New Pen(Color.FromArgb(255, 200, 200, 200)),
                    pHighlight As New Pen(Color.FromArgb(255, 149, 0), 4)
                    Dim TabRect As Rectangle
    
                    For i As Integer = 0 To TabPages.Count - 1
    
                        TabRect = GetTabRect(i)
    
                        If TabRect.Contains(Me.PointToClient(Cursor.Position)) And Not SelectedIndex = i Then
                            'mouse highlight background
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
    
                        ElseIf SelectedIndex = i Then
                            'draw background for selected tab
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
                            'highlight
                            .DrawLine(pHighlight, New Point(TabRect.X - 2, TabRect.Y + ItemSize.Height - 2), New Point(TabRect.X + TabRect.Width - 2, TabRect.Y + ItemSize.Height - 2))
    
                            'draw the button
                            Dim bRect As New Rectangle(-5 + TabRect.X + TabRect.Width - ButtonSize.Width,
                                           CInt(TabRect.Y + (TabRect.Height / 2) - (ButtonSize.Height / 2)),
                                           ButtonSize.Width, ButtonSize.Height)
                            .DrawRectangle(pGray, bRect)
    
                            Select Case MouseState  'color by mouse state
                                Case 1  'mousedown
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), Brushes.Gray, bRect.X + 2, bRect.Y)
                                Case 2  'mousemove
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brHighlight, bRect.X + 2, bRect.Y)
                                Case Else
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brText, bRect.X + 2, bRect.Y)
                            End Select
                        Else
                            .FillRectangle(Brushes.White, TabRect)
                        End If
    
                        'draw the text
                        Dim textSize As SizeF = .MeasureString(TabPages(i).Text, Font)
                        Dim textX As Integer = CInt(TabRect.X + (TabRect.Width / 2) - (textSize.Width / 2))
                        Dim textY As Integer = CInt(TabRect.Y + (TabRect.Height / 2) - (textSize.Height / 2))
                        If TabIcon IsNot Nothing Then textX += CInt(TabIcon.Width / 2)
    
                        .DrawString(TabPages(i).Text, Font, brText, textX, textY + 1)
    
                        'draw the icon
                        .DrawImage(TabIcon, New Rectangle(TabRect.X + 5, CInt(TabRect.Y + (0.2 * TabRect.Height)),
                                        CInt(0.6 * TabRect.Height), CInt(0.6 * TabRect.Height)))
                    Next
    
                    'bottom line 
                    .DrawLine(pGray, New Point(0, ItemSize.Height + 2), New Point(Width, ItemSize.Height + 2))
                End Using
            End With
        End Sub
    
        Private Sub Tab_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
            If SelectedIndex > -1 Then
                MouseState = 1
            Else
                MouseState = 0
            End If
            Invalidate()
        End Sub
    
        Private Sub Tab_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
            If SelectedIndex > -1 Then
                Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
                If tabTextArea.Contains(e.Location) Then
                    If e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                        Cursor = Cursors.Hand
                        If MouseState = 0 Then MouseState = 2
                    Else
                        Cursor = Cursors.Default
                        MouseState = 0
                    End If
                    Invalidate()
                Else
                    Cursor = Cursors.Default
                    MouseState = 0
                End If
            End If
        End Sub
    
        Private Sub Tab_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
            Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
    
            If MouseState = 1 AndAlso e.Button = MouseButtons.Left AndAlso e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                TabPages.Remove(TabPages(SelectedIndex))
            End If
            MouseState = 0
        End Sub
    
        Private Sub Tab_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
            MouseState = 0
        End Sub
    
    End Class
    

    • Marked as answer by ahmeddc Sunday, January 20, 2019 11:47 AM
    Sunday, January 20, 2019 1:10 AM
  • Here is an example using the original including right to left.  :)

    Imports System.Drawing.Drawing2D
    Imports System.Drawing.Text
    
    Public Class Form2
        Private WithEvents Tab1 As New FirefoxSubTabControlEX With {.Parent = Me,
            .Location = New Point(10, 10), .Size = New Size(450, 250)}
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
    
            Tab1.TabPages.Add("Page One")
            Tab1.TabPages.Add("Page Two")
            Tab1.TabPages.Add("Page Three")
            Tab1.ItemSize = New Size(140, 30)
            Tab1.ButtonSize = New Size(18, 18)
            Tab1.Font = New Font("Segoe UI", 10, FontStyle.Regular)
    
            Tab1.RightToLeft = RightToLeft.Yes
            Tab1.RightToLeftLayout = True
    
            'define your own image path
            Tab1.TabIcon = New Bitmap("c:\bitmaps\crlogo16b.ico")
    
        End Sub
    
        Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Tab1.Width = ClientSize.Width - (Tab1.Left * 2)
            Tab1.Height = ClientSize.Height - (Tab1.Top * 2)
            Tab1.Invalidate()
        End Sub
    End Class
    
    Class FirefoxSubTabControlEX
        Inherits TabControl
        Public TabIcon As Bitmap = Nothing
        Public ButtonSize As Size = New Size(16, 16)
        Private MouseState As Integer
    
        Sub New()
            DoubleBuffered = True
            Alignment = TabAlignment.Top
        End Sub
    
        Protected Overrides Sub OnCreateControl()
            MyBase.OnCreateControl()
            SetStyle(ControlStyles.UserPaint, True)
            SizeMode = TabSizeMode.Fixed
        End Sub
    
        Protected Overrides Sub OnControlAdded(ByVal e As ControlEventArgs)
            MyBase.OnControlAdded(e)
            Try
                For i As Integer = 0 To TabPages.Count - 1
                    TabPages(i).BackColor = Color.White
                    TabPages(i).ForeColor = Color.FromArgb(66, 79, 90)
                    TabPages(i).Font = Font
                Next
            Catch
            End Try
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            MyBase.OnPaint(e)
    
            With e.Graphics
                .SmoothingMode = SmoothingMode.HighQuality
                .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
                .Clear(Parent.BackColor)
    
                Using brText As New SolidBrush(Color.FromArgb(56, 69, 80)),
                    brGray As New SolidBrush(Color.FromArgb(255, 240, 240, 240)),
                    brHighlight As New SolidBrush(Color.FromArgb(255, 149, 0)),
                    pGray As New Pen(Color.FromArgb(255, 200, 200, 200)),
                    pHighlight As New Pen(Color.FromArgb(255, 149, 0), 4)
                    Dim TabRect As Rectangle
    
                    For i As Integer = 0 To TabPages.Count - 1
    
                        TabRect = GetTabRect(i)
    
                        If TabRect.Contains(Me.PointToClient(Cursor.Position)) And Not SelectedIndex = i Then
                            'mouse highlight background
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
    
                        ElseIf SelectedIndex = i Then
                            'draw background for selected tab
                            .FillRectangle(brGray, New Rectangle(TabRect.Location.X - 2, TabRect.Location.Y - 2, TabRect.Width, TabRect.Height + 1))
                            'highlight
                            .DrawLine(pHighlight, New Point(TabRect.X - 2, TabRect.Y + ItemSize.Height - 2), New Point(TabRect.X + TabRect.Width - 2, TabRect.Y + ItemSize.Height - 2))
    
                            'draw the button
                            Dim bRect As New Rectangle(-5 + TabRect.X + TabRect.Width - ButtonSize.Width,
                                           CInt(TabRect.Y + (TabRect.Height / 2) - (ButtonSize.Height / 2)),
                                           ButtonSize.Width, ButtonSize.Height)
                            .DrawRectangle(pGray, bRect)
    
                            Select Case MouseState  'color by mouse state
                                Case 1  'mousedown
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), Brushes.Gray, bRect.X + 2, bRect.Y)
                                Case 2  'mousemove
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brHighlight, bRect.X + 2, bRect.Y)
                                Case Else
                                    .DrawString("X", New Font(Font.Name, Font.Size, FontStyle.Bold), brText, bRect.X + 2, bRect.Y)
                            End Select
                        Else
                            .FillRectangle(Brushes.White, TabRect)
                        End If
    
                        'draw the text
                        Dim textSize As SizeF = .MeasureString(TabPages(i).Text, Font)
                        Dim textX As Integer = CInt(TabRect.X + (TabRect.Width / 2) - (textSize.Width / 2))
                        Dim textY As Integer = CInt(TabRect.Y + (TabRect.Height / 2) - (textSize.Height / 2))
                        If TabIcon IsNot Nothing Then textX += CInt(TabIcon.Width / 2)
    
                        .DrawString(TabPages(i).Text, Font, brText, textX, textY + 1)
    
                        'draw the icon
                        .DrawImage(TabIcon, New Rectangle(TabRect.X + 5, CInt(TabRect.Y + (0.2 * TabRect.Height)),
                                        CInt(0.6 * TabRect.Height), CInt(0.6 * TabRect.Height)))
                    Next
    
                    'bottom line 
                    .DrawLine(pGray, New Point(0, ItemSize.Height + 2), New Point(Width, ItemSize.Height + 2))
                End Using
            End With
        End Sub
    
        Private Sub Tab_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
            If SelectedIndex > -1 Then
                MouseState = 1
            Else
                MouseState = 0
            End If
            Invalidate()
        End Sub
    
        Private Sub Tab_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
            If SelectedIndex > -1 Then
                Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
                If tabTextArea.Contains(e.Location) Then
                    If e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                        Cursor = Cursors.Hand
                        If MouseState = 0 Then MouseState = 2
                    Else
                        Cursor = Cursors.Default
                        MouseState = 0
                    End If
                    Invalidate()
                Else
                    Cursor = Cursors.Default
                    MouseState = 0
                End If
            End If
        End Sub
    
        Private Sub Tab_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
            Dim tabTextArea As Rectangle = GetTabRect(SelectedIndex)
    
            If MouseState = 1 AndAlso e.Button = MouseButtons.Left AndAlso e.X > tabTextArea.X + tabTextArea.Width - ButtonSize.Width Then
                TabPages.Remove(TabPages(SelectedIndex))
            End If
            MouseState = 0
        End Sub
    
        Private Sub Tab_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
            MouseState = 0
        End Sub
    
    End Class

    thanks

    how to rotate text font ?

    Sunday, January 20, 2019 3:52 AM
  • Hi,

    Have you found a way to fix these black strips between tabs in RTL mode?

    Tuesday, February 18, 2020 12:37 PM