TabControl with Close and Add Button

前端 未结 3 1024
难免孤独
难免孤独 2020-11-27 21:01

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:

3条回答
  •  [愿得一人]
    2020-11-27 21:33

    As an option you can add an extra tab which shows an add icon Add 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.

    Tab with close and add button

    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 Add and close 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:

    • r-aghaei/TabControlWithCloseButtonAndAddButton

提交回复
热议问题