'My tabControl1 wont show its DrawImage after I added custom backcolor to my tabControl1

I am not really sure where I am going wrong but before I added my custom backcolor to my tabControl1 everything worked fine, I saw the X on other tabs and the + to add tabs

enter image description here

After I added this source of code my Tabs I add are not there but the + button functions and going on other tabs functions aswell making me think that the backColor is just hiding them behind.

            SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
            e.Graphics.FillRectangle(backColor, rec);

enter image description here

Is there like any way that the Tab Pages display fully with the DrawItems I have put in with the backColor?

The code source:

        private void tabControl1_DrawItem_1(object sender, DrawItemEventArgs e)
        {
            Rectangle rec = tabControl1.ClientRectangle;

            SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
            e.Graphics.FillRectangle(backColor, rec);

            StringFormat StrFormat = new StringFormat();
            StrFormat.LineAlignment = StringAlignment.Center;
            StrFormat.Alignment = StringAlignment.Center;

            Brush bshBack = new SolidBrush(Color.FromArgb(55, 55, 55)); // change tab color

            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)
            {
                // Add
                var addImage = Properties.Resources.Add;
                e.Graphics.FillRectangle(bshBack, e.Bounds);
                e.Graphics.DrawImage(addImage,
                    tabRect.Left + (tabRect.Width - addImage.Width) / 2,
                    tabRect.Top + (tabRect.Height - addImage.Height) / 2);
            }
            else
            {
                // Close
                var closeImage = Properties.Resources.Close;
                e.Graphics.FillRectangle(bshBack, e.Bounds);
                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);
            }
        }


Solution 1:[1]

To extend the TabControl with Close and Add Button solution. Create a new class and inherit from the TabControl, set the control styles shown below in the constructor to mainly draw the control and the tabs the way you want it.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

namespace YourProjectNamespace
{
    [DesignerCategory("Code")]
    [ToolboxBitmap(typeof(TabControl))]
    public class TabControlEx : TabControl
    {
        public TabControlEx() : base()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint
                | ControlStyles.ResizeRedraw
                | ControlStyles.OptimizedDoubleBuffer
                | ControlStyles.UserPaint, true);
            UpdateStyles();
            Padding = new Point(14, 4);
        }

        private Color backColor = Color.FromArgb(40, 40, 40);
        /// <inheritdoc cref="Control.BackColor"/>
        [DefaultValue(typeof(Color), "40, 40, 40"),
            Browsable(true),
            EditorBrowsable(EditorBrowsableState.Always),
            DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public new Color BackColor
        {
            get => backColor;
            set
            {
                if (backColor != value)
                {
                    backColor = value;
                    Invalidate();
                }
            }
        }

        private Image addImage;
        [DefaultValue(null)]
        public Image AddButtonImage
        {
            get => addImage;
            set
            {
                addImage = value;
                Invalidate();
            }
        }

        private Image closeImage;
        [DefaultValue(null)]
        public Image CloseButtonImage
        {
            get => closeImage;
            set
            {
                closeImage = value;
                Invalidate();
            }
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            SendMessage(Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
            if (TabCount > 0) TabPages[TabCount - 1].Text = "";
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            var g = e.Graphics;

            g.Clear(BackColor);

            if (TabCount == 0) return;

            for (int i = 0; i < TabCount; i++)
            {
                var tp = TabPages[i];
                var r = Rectangle.Inflate(GetTabRect(i), -4, 0);

                if (i == TabCount - 1)
                {
                    if (AddButtonImage != null)
                        g.DrawImage(AddButtonImage,
                            r.X + (r.Width - AddButtonImage.Width) / 2,
                            r.Y + (r.Height - AddButtonImage.Height) / 2,
                            AddButtonImage.Width, AddButtonImage.Height);
                }
                else
                {
                    if (i == SelectedIndex)
                        using (var brSel = new SolidBrush(Color.FromArgb(105, 105, 105)))
                            g.FillRectangle(brSel, Rectangle.Inflate(r, 4, 1));

                    if (ImageList != null && tp.ImageIndex >= 0)
                        ImageList.Draw(g, 
                            r.X, r.Y + (r.Height - ImageList.ImageSize.Height) / 2, 
                            tp.ImageIndex);

                    if (CloseButtonImage != null)
                    {
                        var closeRect = new Rectangle(new Point(
                            r.Right - CloseButtonImage.Width,
                            r.Y + (r.Height - CloseButtonImage.Height) / 2),
                            CloseButtonImage.Size);

                        g.DrawImage(CloseButtonImage, closeRect,
                            0, 0, CloseButtonImage.Width, CloseButtonImage.Height,
                            GraphicsUnit.Pixel);
                    }

                    TextRenderer.DrawText(g, tp.Text, tp.Font, r, Color.White,
                        TextFormatFlags.HorizontalCenter | 
                        TextFormatFlags.VerticalCenter);
                }
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            var lastIndex = TabCount - 1;
            if (GetTabRect(lastIndex).Contains(e.Location))
            {
                var args = new AddingTabEventArgs();
                OnAddingTab(args);
                if (args.Cancel) return;

                var newTp = new TabPage
                {
                    Text = "New Tab",
                    BackColor = BackColor
                };
                TabPages.Insert(lastIndex, newTp);
                SelectedIndex = lastIndex;
            }
            else
            {
                for (var i = 0; i < TabPages.Count; i++)
                {
                    var r = Rectangle.Inflate(GetTabRect(i), -4, 0);

                    if (new Rectangle(r.Right - 16, r.Y + (r.Height - 16), 16, 16)
                        .Contains(e.Location))
                    {
                        var args = new ClosingTabEventArgs(TabPages[i]);
                        OnClosingTab(args);
                        if (args.Cancel) return;

                        TabPages[i].Dispose();
                        break;
                    }
                }
            }
        }

        protected override void OnSelecting(TabControlCancelEventArgs e)
        {
            if (e.TabPageIndex == TabCount - 1)
                e.Cancel = true;
            else
                base.OnSelecting(e);
        }

        public event EventHandler<ClosingTabEventArgs> ClosingTab;

        protected virtual void OnClosingTab(ClosingTabEventArgs e) => 
            ClosingTab?.Invoke(this, e);

        public event EventHandler<AddingTabEventArgs> AddingTab;

        protected virtual void OnAddingTab(AddingTabEventArgs e) =>
            AddingTab?.Invoke(this, e);

        const int TCM_SETMINTABWIDTH = 0x1300 + 49;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    }

    public class ClosingTabEventArgs : EventArgs
    {
        public ClosingTabEventArgs(TabPage tp) => TabPage = tp;

        public TabPage TabPage { get; }

        public bool Cancel { get; set; }
    }

    public class AddingTabEventArgs : EventArgs
    {
        public AddingTabEventArgs() { }

        public bool Cancel { get; set; }
    }
}

Note, I've added two more events, AddingTab and ClosingTab to trap them in your implementation and do whatever you need, including cancelation.

private void tabControlEx1_AddingTab(object sender, AddingTabEventArgs e)
{
    if (MessageBox.Show("Add new TabPage?", "Alert", 
        MessageBoxButtons.YesNo) == DialogResult.No)
        e.Cancel = true;
}

private void tabControlEx1_ClosingTab(object sender, ClosingTabEventArgs e)
{
    if (MessageBox.Show($"Remove {e.TabPage.Text}?", "Alert", 
        MessageBoxButtons.YesNo) == DialogResult.No)
        e.Cancel = true;
}

Of course, you can extend the control more and add more drawing properties like the back/foreground colors of the normal and selected tabs. Also, you can try the LinearGradientBrush to fill the backgrounds instead of the solid brushes.

Rebuild, on the top of the ToolBox window, find and drop an instance. Try and go back to the code to add your touch.

SOQ72179300

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1