-
Jul 21st, 2010, 06:22 AM
#1
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:
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() 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
Last edited by Pradeep1210; Jul 21st, 2010 at 10:37 AM.
Reason: better support for inheritence
-
Jul 21st, 2010, 06:49 AM
#2
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?
-
Jul 21st, 2010, 07:02 AM
#3
Re: TabControl with Close button on TabPages (with Design-Time support)
Originally Posted by NickThissen
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
Originally Posted by NickThissen
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.
-
Jul 30th, 2010, 01:01 AM
#4
Lively Member
Re: TabControl with Close button on TabPages (with Design-Time support)
its good...but the button looks like doodoo...
-
Jul 30th, 2010, 05:04 AM
#5
Re: TabControl with Close button on TabPages (with Design-Time support)
Originally Posted by reconrey
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.
-
Aug 17th, 2010, 01:42 PM
#6
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...
-
Aug 18th, 2010, 02:22 PM
#7
Frenzied Member
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...
-
Aug 18th, 2010, 03:32 PM
#8
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.
-
Mar 10th, 2011, 07:28 PM
#9
New Member
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
-
Mar 10th, 2011, 07:46 PM
#10
New Member
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!)
Originally Posted by samneric
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
-
Jan 2nd, 2012, 06:08 PM
#11
Addicted Member
Re: TabControl with Close button on TabPages (with Design-Time support)
-
Aug 31st, 2013, 01:35 AM
#12
New Member
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...
Originally Posted by Pradeep1210
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:
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()
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
-
Sep 6th, 2013, 12:14 PM
#13
New Member
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.
-
Dec 13th, 2014, 03:27 AM
#14
Registered User
-
Dec 13th, 2014, 03:31 AM
#15
Registered User
Re: TabControl with Close button on TabPages (with Design-Time support)
-
Feb 4th, 2015, 08:25 PM
#16
New Member
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...
-
Aug 26th, 2015, 02:28 PM
#17
New Member
Re: TabControl with Close button on TabPages (with Design-Time support)
Originally Posted by minitech
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?
-
Dec 11th, 2015, 06:29 AM
#18
New Member
Re: TabControl with Close button on TabPages (with Design-Time support)
Originally Posted by mkschoenrock
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
-
Sep 18th, 2017, 03:32 PM
#19
Addicted Member
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...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|