Results 1 to 19 of 19

Thread: TabControl with Close button on TabPages (with Design-Time support)

  1. #1

    Thread Starter
    VB Addict Pradeep1210's Avatar
    Join Date
    Apr 2004
    Location
    Inside the CPU...
    Posts
    6,614

    TabControl with Close button on TabPages (with Design-Time support)

    This article shows how to add a close button to the tabs on your TabControl.

    Usage:
    1. Add a new class to your application (preferably named TabControlEx.vb)
    2. Copy and paste this code into that class.
    3. Rebuild.
    4. Now you should see a new item in the Control Toolbox named TabControlEx. Drag this control to your form.

    Features:
    1. The ShowCloseButtonOnTabs property controls whether close button is shown on the tabs on not. By default this is True.
    2. The CloseButtonClick event is raised when any of the close buttons is clicked. By default this closes the tab, but you can set the e.Cancel = True inside this event handler to prevent closing the tab.

    vb.net Code:
    1. Option Strict On
    2. Imports System.ComponentModel
    3.  
    4. <ToolboxBitmap(GetType(System.Windows.Forms.TabControl))> _
    5. Public Class TabControlEx
    6.     Inherits TabControl
    7.  
    8.     Private Declare Auto Function SetParent Lib "user32" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
    9.     Protected CloseButtonCollection As New Dictionary(Of Button, TabPage)
    10.     Private _ShowCloseButtonOnTabs As Boolean = True
    11.  
    12.     <Browsable(True), DefaultValue(True), Category("Behavior"), Description("Indicates whether a close button should be shown on each TabPage")> _
    13.     Public Property ShowCloseButtonOnTabs() As Boolean
    14.         Get
    15.             Return _ShowCloseButtonOnTabs
    16.         End Get
    17.         Set(ByVal value As Boolean)
    18.             _ShowCloseButtonOnTabs = value
    19.             For Each btn In CloseButtonCollection.Keys
    20.                 btn.Visible = _ShowCloseButtonOnTabs
    21.             Next
    22.             RePositionCloseButtons()
    23.         End Set
    24.     End Property
    25.  
    26.     Protected Overrides Sub OnCreateControl()
    27.         MyBase.OnCreateControl()
    28.         RePositionCloseButtons()
    29.     End Sub
    30.  
    31.     Protected Overrides Sub OnControlAdded(ByVal e As System.Windows.Forms.ControlEventArgs)
    32.         MyBase.OnControlAdded(e)
    33.         Dim tp As TabPage = DirectCast(e.Control, TabPage)
    34.         Dim rect As Rectangle = Me.GetTabRect(Me.TabPages.IndexOf(tp))
    35.         Dim btn As Button = AddCloseButton(tp)
    36.         btn.Size = New Size(rect.Height - 1, rect.Height - 1)
    37.         btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
    38.         SetParent(btn.Handle, Me.Handle)
    39.         AddHandler btn.Click, AddressOf OnCloseButtonClick
    40.         CloseButtonCollection.Add(btn, tp)
    41.     End Sub
    42.  
    43.     Protected Overrides Sub OnControlRemoved(ByVal e As System.Windows.Forms.ControlEventArgs)
    44.         Dim btn As Button = CloseButtonOfTabPage(DirectCast(e.Control, TabPage))
    45.         RemoveHandler btn.Click, AddressOf OnCloseButtonClick
    46.         CloseButtonCollection.Remove(btn)
    47.         SetParent(btn.Handle, Nothing)
    48.         btn.Dispose()
    49.         MyBase.OnControlRemoved(e)
    50.     End Sub
    51.  
    52.     Protected Overrides Sub OnLayout(ByVal levent As System.Windows.Forms.LayoutEventArgs)
    53.         MyBase.OnLayout(levent)
    54.         RePositionCloseButtons()
    55.     End Sub
    56.  
    57.     Public Event CloseButtonClick As CancelEventHandler
    58.     Protected Overridable Sub OnCloseButtonClick(ByVal sender As Object, ByVal e As EventArgs)
    59.         If Not DesignMode Then
    60.             Dim btn As Button = DirectCast(sender, Button)
    61.             Dim tp As TabPage = CloseButtonCollection(btn)
    62.             Dim ee As New CancelEventArgs
    63.             RaiseEvent CloseButtonClick(sender, ee)
    64.             If Not ee.Cancel Then
    65.                 Me.TabPages.Remove(tp)
    66.                 RePositionCloseButtons()
    67.             End If
    68.         End If
    69.     End Sub
    70.  
    71.     Protected Overridable Function AddCloseButton(ByVal tp As TabPage) As Button
    72.         Dim closeButton As New Button
    73.         With closeButton
    74.             '' TODO: Give a good visual appearance to the Close button, maybe by assigning images etc.
    75.             ''       Here I have not used images to keep things simple.
    76.             .Text = "X"
    77.             .FlatStyle = FlatStyle.Flat
    78.             .BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
    79.             .ForeColor = Color.White
    80.             .Font = New Font("Microsoft Sans Serif", 6, FontStyle.Bold)
    81.         End With
    82.         Return closeButton
    83.     End Function
    84.  
    85.     Public Sub RePositionCloseButtons()
    86.         For Each item In CloseButtonCollection
    87.             RePositionCloseButtons(item.Value)
    88.         Next
    89.     End Sub
    90.  
    91.     Public Sub RePositionCloseButtons(ByVal tp As TabPage)
    92.         Dim btn As Button = CloseButtonOfTabPage(tp)
    93.         If btn IsNot Nothing Then
    94.             Dim tpIndex As Integer = Me.TabPages.IndexOf(tp)
    95.             If tpIndex >= 0 Then
    96.                 Dim rect As Rectangle = Me.GetTabRect(tpIndex)
    97.                 If Me.SelectedTab Is tp Then
    98.                     btn.BackColor = Color.Red
    99.                     btn.Size = New Size(rect.Height - 1, rect.Height - 1)
    100.                     btn.Location = New Point(rect.X + rect.Width - rect.Height, rect.Y + 1)
    101.                 Else
    102.                     btn.BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
    103.                     btn.Size = New Size(rect.Height - 3, rect.Height - 3)
    104.                     btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
    105.                 End If
    106.                 btn.Visible = ShowCloseButtonOnTabs
    107.                 btn.BringToFront()
    108.             End If
    109.         End If
    110.     End Sub
    111.  
    112.     Protected Function CloseButtonOfTabPage(ByVal tp As TabPage) As Button
    113.         Return (From item In CloseButtonCollection Where item.Value Is tp Select item.Key).FirstOrDefault
    114.     End Function
    115. End Class
    Last edited by Pradeep1210; Jul 21st, 2010 at 10:37 AM. Reason: better support for inheritence
    Pradeep, Microsoft MVP (Visual Basic)
    Please appreciate posts that have helped you by clicking icon on the left of the post.
    "A problem well stated is a problem half solved." — Charles F. Kettering

    Read articles on My Blog • 101 LINQ Samples • JSON Validator • XML Schema Validator • "How Do I" videos on MSDN • VB.NET and C# Comparison • Good Coding Practices • VBForums Reputation Saver • String Enum • Super Simple Tetris Game


    (2010-2013)
    NB: I do not answer coding questions via PM. If you want my help, then make a post and PM me it's link. If I can help, trust me I will...

  2. #2
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: TabControl with Close button on TabPages (with Design-Time support)

    This is pretty good! I've wanted to do this for a while but I've never thought of doing it like this, I've always thought the only way would be to custom draw the tab headers, in which case it is impossible (I think) to have them automatically assume the system theme.

    The only down-side to this approach is that the buttons are created on top of the text in the tabpage header (at least if they are set to auto-size). I don't suppose it's possible to make every tabpage header a few pixels wider, while still maintaining the auto-size ability?

  3. #3

    Thread Starter
    VB Addict Pradeep1210's Avatar
    Join Date
    Apr 2004
    Location
    Inside the CPU...
    Posts
    6,614

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Quote Originally Posted by NickThissen View Post
    This is pretty good! I've wanted to do this for a while but I've never thought of doing it like this, I've always thought the only way would be to custom draw the tab headers, in which case it is impossible (I think) to have them automatically assume the system theme.
    Thanks

    Quote Originally Posted by NickThissen View Post
    The only down-side to this approach is that the buttons are created on top of the text in the tabpage header (at least if they are set to auto-size). I don't suppose it's possible to make every tabpage header a few pixels wider, while still maintaining the auto-size ability?
    I never thought in these terms. I'll give it a try and let you know if I get to something.
    Pradeep, Microsoft MVP (Visual Basic)
    Please appreciate posts that have helped you by clicking icon on the left of the post.
    "A problem well stated is a problem half solved." — Charles F. Kettering

    Read articles on My Blog • 101 LINQ Samples • JSON Validator • XML Schema Validator • "How Do I" videos on MSDN • VB.NET and C# Comparison • Good Coding Practices • VBForums Reputation Saver • String Enum • Super Simple Tetris Game


    (2010-2013)
    NB: I do not answer coding questions via PM. If you want my help, then make a post and PM me it's link. If I can help, trust me I will...

  4. #4
    Lively Member
    Join Date
    Feb 2010
    Posts
    106

    Re: TabControl with Close button on TabPages (with Design-Time support)

    its good...but the button looks like doodoo...

  5. #5

    Thread Starter
    VB Addict Pradeep1210's Avatar
    Join Date
    Apr 2004
    Location
    Inside the CPU...
    Posts
    6,614

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Quote Originally Posted by reconrey View Post
    its good...but the button looks like doodoo...
    You can modify the AddCloseButton procedure to give whatever look you want for the button.
    What I showed in the demo is just a simple button with red background color. But you can use graphical images etc. to give it a better look.
    Pradeep, Microsoft MVP (Visual Basic)
    Please appreciate posts that have helped you by clicking icon on the left of the post.
    "A problem well stated is a problem half solved." — Charles F. Kettering

    Read articles on My Blog • 101 LINQ Samples • JSON Validator • XML Schema Validator • "How Do I" videos on MSDN • VB.NET and C# Comparison • Good Coding Practices • VBForums Reputation Saver • String Enum • Super Simple Tetris Game


    (2010-2013)
    NB: I do not answer coding questions via PM. If you want my help, then make a post and PM me it's link. If I can help, trust me I will...

  6. #6
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Wow... so simple! It's great. Too bad you can't change the style of the tabs like this, though...

  7. #7
    Frenzied Member
    Join Date
    Jul 2006
    Location
    MI
    Posts
    1,965

    Re: TabControl with Close button on TabPages (with Design-Time support)

    What this control needs is a "+" at the end, that when clicked adds a new tabpage to the control, like most browsers have, but the "+" tab wouldn't have a close button on it.
    Also, how do you add a new tabpage to this control programatically? Thanks...

  8. #8
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Just use a button for the "+", not a tab. The code would be easy enough to modify - 10 pixels to the right of the last X button, add a + button.

  9. #9
    New Member
    Join Date
    Mar 2011
    Posts
    2

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Buttons overwrite text?

    Try this....

    Code:
        Protected Overrides Sub OnCreateControl()
    
            MyBase.OnCreateControl()
    
            For Each item In CloseButtonCollection
    
                item.Value.Text = item.Value.Text.Trim & Space(4)
    
            Next
    
    
            RePositionCloseButtons()
    
        End Sub
    Steve

  10. #10
    New Member
    Join Date
    Mar 2011
    Posts
    2

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Or just put the item.value statement in the proc 'RePositionCloseButtons' (changing 'item.value' to 'tabpage' of course!)





    Quote Originally Posted by samneric View Post
    Buttons overwrite text?

    Try this....

    Code:
        Protected Overrides Sub OnCreateControl()
    
            MyBase.OnCreateControl()
    
            For Each item In CloseButtonCollection
    
                item.Value.Text = item.Value.Text.Trim & Space(4)
    
            Next
    
    
            RePositionCloseButtons()
    
        End Sub
    Steve

  11. #11
    Addicted Member lecfox's Avatar
    Join Date
    Dec 2011
    Location
    Jamaica
    Posts
    174

    Re: TabControl with Close button on TabPages (with Design-Time support)

    how do u rebuild?

  12. #12
    New Member
    Join Date
    Aug 2013
    Posts
    1

    Resolved Re: TabControl with Close button on TabPages (with Design-Time support)

    you are really helping other. and one more thing your are very inteligent with helping nature. please continue to help us.

    One more time.

    THANK YOU...






    Quote Originally Posted by Pradeep1210 View Post
    This article shows how to add a close button to the tabs on your TabControl.

    Usage:
    1. Add a new class to your application (preferably named TabControlEx.vb)
    2. Copy and paste this code into that class.
    3. Rebuild.
    4. Now you should see a new item in the Control Toolbox named TabControlEx. Drag this control to your form.

    Features:
    1. The ShowCloseButtonOnTabs property controls whether close button is shown on the tabs on not. By default this is True.
    2. The CloseButtonClick event is raised when any of the close buttons is clicked. By default this closes the tab, but you can set the e.Cancel = True inside this event handler to prevent closing the tab.

    vb.net Code:
    1. Option Strict On
    2. Imports System.ComponentModel
    3.  
    4. <ToolboxBitmap(GetType(System.Windows.Forms.TabControl))> _
    5. Public Class TabControlEx
    6.     Inherits TabControl
    7.  
    8.     Private Declare Auto Function SetParent Lib "user32" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
    9.     Protected CloseButtonCollection As New Dictionary(Of Button, TabPage)
    10.     Private _ShowCloseButtonOnTabs As Boolean = True
    11.  
    12.     <Browsable(True), DefaultValue(True), Category("Behavior"), Description("Indicates whether a close button should be shown on each TabPage")> _
    13.     Public Property ShowCloseButtonOnTabs() As Boolean
    14.         Get
    15.             Return _ShowCloseButtonOnTabs
    16.         End Get
    17.         Set(ByVal value As Boolean)
    18.             _ShowCloseButtonOnTabs = value
    19.             For Each btn In CloseButtonCollection.Keys
    20.                 btn.Visible = _ShowCloseButtonOnTabs
    21.             Next
    22.             RePositionCloseButtons()
    23.         End Set
    24.     End Property
    25.  
    26.     Protected Overrides Sub OnCreateControl()
    27.         MyBase.OnCreateControl()
    28.         RePositionCloseButtons()
    29.     End Sub
    30.  
    31.     Protected Overrides Sub OnControlAdded(ByVal e As System.Windows.Forms.ControlEventArgs)
    32.         MyBase.OnControlAdded(e)
    33.         Dim tp As TabPage = DirectCast(e.Control, TabPage)
    34.         Dim rect As Rectangle = Me.GetTabRect(Me.TabPages.IndexOf(tp))
    35.         Dim btn As Button = AddCloseButton(tp)
    36.         btn.Size = New Size(rect.Height - 1, rect.Height - 1)
    37.         btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
    38.         SetParent(btn.Handle, Me.Handle)
    39.         AddHandler btn.Click, AddressOf OnCloseButtonClick
    40.         CloseButtonCollection.Add(btn, tp)
    41.     End Sub
    42.  
    43.     Protected Overrides Sub OnControlRemoved(ByVal e As System.Windows.Forms.ControlEventArgs)
    44.         Dim btn As Button = CloseButtonOfTabPage(DirectCast(e.Control, TabPage))
    45.         RemoveHandler btn.Click, AddressOf OnCloseButtonClick
    46.         CloseButtonCollection.Remove(btn)
    47.         SetParent(btn.Handle, Nothing)
    48.         btn.Dispose()
    49.         MyBase.OnControlRemoved(e)
    50.     End Sub
    51.  
    52.     Protected Overrides Sub OnLayout(ByVal levent As System.Windows.Forms.LayoutEventArgs)
    53.         MyBase.OnLayout(levent)
    54.         RePositionCloseButtons()
    55.     End Sub
    56.  
    57.     Public Event CloseButtonClick As CancelEventHandler
    58.     Protected Overridable Sub OnCloseButtonClick(ByVal sender As Object, ByVal e As EventArgs)
    59.         If Not DesignMode Then
    60.             Dim btn As Button = DirectCast(sender, Button)
    61.             Dim tp As TabPage = CloseButtonCollection(btn)
    62.             Dim ee As New CancelEventArgs
    63.             RaiseEvent CloseButtonClick(sender, ee)
    64.             If Not ee.Cancel Then
    65.                 Me.TabPages.Remove(tp)
    66.                 RePositionCloseButtons()
    67.             End If
    68.         End If
    69.     End Sub
    70.  
    71.     Protected Overridable Function AddCloseButton(ByVal tp As TabPage) As Button
    72.         Dim closeButton As New Button
    73.         With closeButton
    74.             '' TODO: Give a good visual appearance to the Close button, maybe by assigning images etc.
    75.             ''       Here I have not used images to keep things simple.
    76.             .Text = "X"
    77.             .FlatStyle = FlatStyle.Flat
    78.             .BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
    79.             .ForeColor = Color.White
    80.             .Font = New Font("Microsoft Sans Serif", 6, FontStyle.Bold)
    81.         End With
    82.         Return closeButton
    83.     End Function
    84.  
    85.     Public Sub RePositionCloseButtons()
    86.         For Each item In CloseButtonCollection
    87.             RePositionCloseButtons(item.Value)
    88.         Next
    89.     End Sub
    90.  
    91.     Public Sub RePositionCloseButtons(ByVal tp As TabPage)
    92.         Dim btn As Button = CloseButtonOfTabPage(tp)
    93.         If btn IsNot Nothing Then
    94.             Dim tpIndex As Integer = Me.TabPages.IndexOf(tp)
    95.             If tpIndex >= 0 Then
    96.                 Dim rect As Rectangle = Me.GetTabRect(tpIndex)
    97.                 If Me.SelectedTab Is tp Then
    98.                     btn.BackColor = Color.Red
    99.                     btn.Size = New Size(rect.Height - 1, rect.Height - 1)
    100.                     btn.Location = New Point(rect.X + rect.Width - rect.Height, rect.Y + 1)
    101.                 Else
    102.                     btn.BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
    103.                     btn.Size = New Size(rect.Height - 3, rect.Height - 3)
    104.                     btn.Location = New Point(rect.X + rect.Width - rect.Height - 1, rect.Y + 1)
    105.                 End If
    106.                 btn.Visible = ShowCloseButtonOnTabs
    107.                 btn.BringToFront()
    108.             End If
    109.         End If
    110.     End Sub
    111.  
    112.     Protected Function CloseButtonOfTabPage(ByVal tp As TabPage) As Button
    113.         Return (From item In CloseButtonCollection Where item.Value Is tp Select item.Key).FirstOrDefault
    114.     End Function
    115. End Class

  13. #13
    New Member
    Join Date
    Sep 2013
    Posts
    1

    Re: TabControl with Close button on TabPages (with Design-Time support)

    I've found this article, how to add close button to tab headers in TabControl is explained in details.

  14. #14
    Registered User
    Join Date
    Dec 2014
    Posts
    2

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Thank you very much sir for this effort you gave to us! I really appreciate your kindness. I hope you will continue to share your knowledge to the needy .

    Anyways guys! I have managed to edit some codes to change the appearance of the close button. Please see in the screenshot

    Name:  Untitled.jpg
Views: 11520
Size:  33.9 KB

    Name:  1.jpg
Views: 11172
Size:  19.0 KB

  15. #15
    Registered User
    Join Date
    Dec 2014
    Posts
    2

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Very nice

  16. #16
    New Member
    Join Date
    Feb 2015
    Posts
    1

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Wondering: I am adding a tab named "ADDTAB" with a text value of "+" to be displayed. I would like to NOT have a close button on this tab. So, where in this class would I put something like... if thistabpage.name = "ADDTAB" then do not add closebutton. .. I've been trying for a bit and cant seem to get it... Thanks for any help...

  17. #17
    New Member
    Join Date
    Aug 2015
    Posts
    1

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Quote Originally Posted by minitech View Post
    Just use a button for the "+", not a tab. The code would be easy enough to modify - 10 pixels to the right of the last X button, add a + button.
    Can someone tell me how i can do this?

  18. #18
    New Member
    Join Date
    Nov 2014
    Posts
    3

    Re: TabControl with Close button on TabPages (with Design-Time support)

    Quote Originally Posted by mkschoenrock View Post
    Wondering: I am adding a tab named "ADDTAB" with a text value of "+" to be displayed. I would like to NOT have a close button on this tab. So, where in this class would I put something like... if thistabpage.name = "ADDTAB" then do not add closebutton. .. I've been trying for a bit and cant seem to get it... Thanks for any help...
    it worked for me..

    Code:
    Protected Overrides Sub OnControlAdded(ByVal e As System.Windows.Forms.ControlEventArgs)
            MyBase.OnControlAdded(e)
            Dim tp As TabPage = DirectCast(e.Control, TabPage)
    
            If tp.Text = "+" Then Exit Sub ' add close buttons <--------
    
            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)
    
    'for dynamic created tab <--------
            For Each item In CloseButtonCollection
                item.Value.Text = item.Value.Text.Trim & Space(8)
            Next
            RePositionCloseButtons()
        End Sub

  19. #19
    Addicted Member
    Join Date
    Dec 2011
    Posts
    194

    Re: TabControl with Close button on TabPages (with Design-Time support)

    @Pradeep1210 Thank you!

    I have a problem with TabControlEx, when set Multiline property to True or change Appearance, all close buttons disappear, i tried to call the method RePositionCloseButtons after changing these properties but it didn't work!

    Please help...
    On Error GoTo Hell

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width