I'm tring to make a tab control have a "x" (close button) and "+" (new tab button). I found a solution to add a x button
, the tab looks like this now:
But I want to add a +
where's that black circle right now. I have no idea how, I tried draw on Paint
event of the last tab, like this:
var p = tabs.TabPages[tabs.TabCount - 1];
p.Paint += new PaintEventHandler(tab_OnDrawPage);
private void tab_OnDrawPage(object sender, PaintEventArgs e)
{
// e.ClipRectangle.
e.Graphics.DrawString("+",
new Font("verdana",
10,
FontStyle.Bold),
Brushes.Black,
e.ClipRectangle.X + 10,
e.ClipRectangle.Y + 10);
}
But it didn't show anything draw. I guess it has to do with the positions I passed to DrawString()
call, but I don't know the proper ones to use. I used +10 to draw it away from last tab. How to fix that?. I haven't done any custom drawing myself, I'm learning it.
As an option you can add an extra tab which shows an add icon and check when the user clicks on that tab, then insert a new TabPage
before it.
Also you can prevent selecting that extra tab simply using Selecting
event of TabControl
. This way the last tab acts only like an add button for you, like IE and Chrome.
Implementation Details
We will use an owner draw tab to show close icons on each tab an add icon on the last tab. We use DrawItem
to draw close and add icons, MouseDown
to handle click on close and add buttons, Selecting
to prevent selecting of the last tab and HandleCreated
to adjust tab width. You can see all implementation settings and codes below.
Initialization
Set padding and DrawMode
and assign event handlers for DrawItem
, MouseDown
, Selecting
and HandleCreated
event.
this.tabControl1.Padding = new Point(12, 4);
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += tabControl1_DrawItem;
this.tabControl1.MouseDown += tabControl1_MouseDown;
this.tabControl1.Selecting += tabControl1_Selecting;
this.tabControl1.HandleCreated += tabControl1_HandleCreated;
Handle click on close button and add button
You can handle MouseDown
or MouseClick
event and check if the last tab rectangle contains the mouse clicked point, then insert a tab before the last tab. Otherwose check if one of close buttons contains clicked location, then close the tab which its close button was clicked:
private void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
var lastIndex = this.tabControl1.TabCount - 1;
if (this.tabControl1.GetTabRect(lastIndex).Contains(e.Location))
{
this.tabControl1.TabPages.Insert(lastIndex, "New Tab");
this.tabControl1.SelectedIndex = lastIndex;
}
else
{
for (var i = 0; i < this.tabControl1.TabPages.Count; i++)
{
var tabRect = this.tabControl1.GetTabRect(i);
tabRect.Inflate(-2, -2);
var closeImage = Properties.Resources.DeleteButton_Image;
var imageRect = new Rectangle(
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2,
closeImage.Width,
closeImage.Height);
if (imageRect.Contains(e.Location))
{
this.tabControl1.TabPages.RemoveAt(i);
break;
}
}
}
}
Prevent selectin last tab
To prevent selection the last tab, you can handle Selecting
event of control and check if the selecting tab is the last tab, cancel the event:
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPageIndex == this.tabControl1.TabCount - 1)
e.Cancel = true;
}
Draw Close Button and Add Button
To draw close button and add button, you can handle DrawItem
event. I used these icons for add and close buttons.
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
var tabPage = this.tabControl1.TabPages[e.Index];
var tabRect = this.tabControl1.GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
if (e.Index == this.tabControl1.TabCount - 1)
{
var addImage = Properties.Resources.AddButton_Image;
e.Graphics.DrawImage(addImage,
tabRect.Left + (tabRect.Width - addImage.Width) / 2,
tabRect.Top + (tabRect.Height - addImage.Height) / 2);
}
else
{
var closeImage = Properties.Resources.DeleteButton_Image;
e.Graphics.DrawImage(closeImage,
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font,
tabRect, tabPage.ForeColor, TextFormatFlags.Left);
}
}
Adjust Tab width
To adjust tab width and let the last tab have smaller width, you can hanlde HandleCreated
event and send a TCM_SETMINTABWIDTH
to the control and specify the minimum size allowed for the tab width:
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int TCM_SETMINTABWIDTH = 0x1300 + 49;
private void tabControl1_HandleCreated(object sender, EventArgs e)
{
SendMessage(this.tabControl1.Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
}
Download
You can download the code or clone the repository here: