34

I am struggling to find a way to color the tab headers of a tabpage in WinForms. There are solutions to color the current indexed tab using the OnDrawItem event, but is it possible to color all the tabs with different colors to make them more intuitive for users for certain behavior?

Thanks in advance.

Sildoreth
  • 1,883
  • 1
  • 25
  • 38
Rajeev Ranjan Lal
  • 641
  • 2
  • 7
  • 12

3 Answers3

60

An improved version of Ash's answer:

private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
{
    TabPage page = tabControl.TabPages[e.Index];
    e.Graphics.FillRectangle(new SolidBrush(page.BackColor), e.Bounds);

    Rectangle paddedBounds = e.Bounds;
    int yOffset = (e.State == DrawItemState.Selected) ? -2 : 1;
    paddedBounds.Offset(1, yOffset);
    TextRenderer.DrawText(e.Graphics, page.Text, e.Font, paddedBounds, page.ForeColor);
}

This code uses the TextRenderer class to draw its text (as .NET does), fixes problems with font clipping/wrapping by not negatively inflating the bounds, and takes tab selection into account.

Thanks to Ash for the original code.

g t
  • 7,287
  • 7
  • 50
  • 85
  • 3
    This ONLY works if you set your tab control's DrawMode to OwnerDrawFixed - the DrawItem event never fires if it's set to Normal. – Nitesh Feb 06 '17 at 19:57
  • 4
    @Nitesh this answer is based on Ash's answer and that answer indicates that the property DrawMode is set to OwnerDrawFixed. – Xam Jul 28 '19 at 21:02
  • If you need to [raise the DrawItem event](https://stackoverflow.com/a/33577329/3585500) call `tabControl.Invalidate()`. Like if you ever change the tab page backcolor while its running or whatever. – ourmandave Jul 08 '21 at 16:30
  • @g-t is it possible also to cover/color the tab header bottom part white border/area, please check the image here ibb.co/n1F1p57, it's looks odd for that white bottom border on non selected tab headers. THANKS IN ADVANCE – SalmaBegum Aug 08 '23 at 01:56
  • @SalmaBegum It looks like the white area is part of the borders of the tab control item and tab control itself. Perhaps adjusting the bounds passed to `FillRectangle()` would work? Otherwise you might have to raise a separate question. – g t Aug 09 '23 at 07:42
38

Yes, there is no need for any win32 code. You just need to set the tab controls DrawMode property to 'OwnerDrawFixed' and then handle the tab control's DrawItem event.

The following code shows how:

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    // This event is called once for each tab button in your tab control

    // First paint the background with a color based on the current tab

   // e.Index is the index of the tab in the TabPages collection.
    switch (e.Index )
    {
        case 0:
            e.Graphics.FillRectangle(new SolidBrush(Color.Red), e.Bounds);
            break;
        case 1:
            e.Graphics.FillRectangle(new SolidBrush(Color.Blue), e.Bounds);
            break;
        default:
            break;
    }

    // Then draw the current tab button text 
    Rectangle paddedBounds=e.Bounds;
    paddedBounds.Inflate(-2,-2);  
    e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.HighlightText, paddedBounds);

}

Setting the DrawMode to 'OwnerDrawnFixed' means each tab button has to be the same size (ie Fixed).

However if you want to change the size of all tab buttons, you can set the tab control's SizeMode property to 'Fixed' and then change the ItemSize property.

Ash
  • 60,973
  • 31
  • 151
  • 169
  • 5
    Works great, but how would you change the color of the area behind the tabs? – Roast May 04 '12 at 16:04
  • 1
    After all, the question was for the tabs headers, not general user draw – John Stock Jul 31 '19 at 13:50
  • @ash, is it possible also to cover/color the tab header bottom part white border/area, please check the image here https://ibb.co/n1F1p57, it's looks odd for that white bottom border on non selected tab headers. THANKS IN ADVANCE – SalmaBegum Aug 07 '23 at 18:22
2

Using the current tab control, if it is possible you'd need to hook a lot of win-32 events (there may be a pre-wrapped implementation out there). Another alternative would be a 3rd-party tabbed control replacement; I'm sure plenty of vendors will sell you one.

IMO, you might find it less pain to look at WPF; it is a big change, but has more control over things like this. You can host WPF inside winforms if needed (if you can't justify a full make-over, which is a pretty common reality).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900