Click here to Skip to main content
Click here to Skip to main content

Painting Your Own Tabs

, 3 Jul 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
How to control the painting of the .NET TabControl
Sample Image - CustomTabControl.png

Second Edition of this Control Now Available

I have now released a much improved version of this control as Painting Your Own Tabs - the second edition is available here which includes new styling, a re-worked painting metaphor, and a totally different approach to transparency. I did not want to replace this article and code as I know many people are using it, however I do recommend you update to the new version if you can. It is much better.

Introduction

A project I have been working on required a tabbed user interface, and for some time, we had been using the excellent tab control from Infragistics. However, I wanted to use the native .NET TabControl, for such a core part of the system where the speed was vital. It doesn't seem like much, but the Infragistics controls are custom drawn from the ground up, and that does make a difference. The more you can use the native control set, the faster your application will run.

When VS.NET 2005 was released, I was hoping that the TabControl would support the style used in the VS IDE, as that was the style we wanted to use. Unfortunately, this was not the case. Furthermore, I had noted that the native TabControl and the Infragistics tab control both had a grey border around the tab page section, as you can see from the image above. I really wanted to be able to control this colour. Having searched the web, I found that everyone was using the Infragistics technique, including some good articles here on CodeProject. However, replicating a control created by Microsoft, available out of the box, when I just wanted to tweak it, did not sound like fun to me!

So, having decided to subclass the native TabControl, I had just two problems to solve. Firstly, how to paint the tabs themselves to make them look like the VS.NET IDE, without losing any of the auto sizing functionality. Secondly, how to get rid of that annoying grey background!

There was a third part to this, I had to add the tab closer and the tab navigation buttons to the top right corner of the control. I did that myself, but the solution is a bit flaky so I have left that out of this article.

Using the Code

The solution I came up with is shown in my demo application, and consists of the sub classed TabControl itself, and a themed colour provider. I used an updated version of the themed colour provider I wrote for an earlier article on theming the CheckBox control.

To use the control in your own applications, just copy the two classes into your code.

I used SharpDevelop 2.0 to create the solution, and it works fine from VS.NET 2005 as well. I have included both a C# version and a VB.NET version in the solution, though the article code snippets are from the VB.NET version. It should be possible to do the same thing in .NET 1.0 or 1.1, but I am working exclusively in .NET 2.0 now.

So, how did I solve the problems?

The SDK explains how you can set the TabControl Drawmode to OwnerDrawFixed to paint the tabs yourself; however, the tabs do not resize for longer captions, and there is a really annoying border painted on each tab that you just can't get rid of.

So, I found that you can set the control style to UserPaint and do it all yourself. This keeps the auto sizing tabs, and all the tab page functionality remains intact. I also set the height of the tabs to 15 pixels, to match the size of the tabs in the VS IDE. Setting the width to zero makes the tabs auto-size to fit long captions. I also added a property to switch between using the native painting and my custom painting.

Me.SetStyle(ControlStyles.UserPaint, True)
Me.ItemSize = New Size(0, 15)

The simplest solution to getting rid of the grey border turned out to be to set the control to have a transparent background and set the colour of the containing control. Unfortunately, invoking the Paint event of the parent control tends to crash in the designer, so I set it to a nice gradient at design time. First, you enable transparency support:

Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)

Then, you override the OnPaintBackground method to invoke the parent control's Paint method:

Protected Overrides Sub OnPaintBackground( _
    ByVal pevent As System.Windows.Forms.PaintEventArgs)
    If Me.DesignMode Then
        ' If this is in the designer let's put a nice gradient on the back
        ' By default the tabcontrol has a fixed grey background. Yuck!
        Dim backBrush As New LinearGradientBrush( _
            Me.Bounds, _
            SystemColors.ControlLightLight, _
            SystemColors.ControlLight, _
            Drawing2D.LinearGradientMode.Vertical)
        pevent.Graphics.FillRectangle(backBrush, Me.Bounds)
        backBrush.Dispose()
    Else
        ' At runtime we want a transparent background.
        ' So let's paint the containing control (there has to be one).
        Me.InvokePaintBackground(Me.Parent, pevent)
        Me.InvokePaint(Me.Parent, pevent)
    End If
End Sub

Painting the tabs is a little trickier. Most of the time, only the currently selected tab and the previously selected tab repaint. The clip rectangle of the PaintEventArgs restricts the area that is being asked to paint itself. However, you have to supply code to paint all the tabs, and paint the currently selected tab differently within that. Any painting code that paints outside of the requested clip rectangle just doesn't do anything.

I have broken down the tab painting into a number of stages. See my code for details.

  1. For each tab, paint the background, border, and text. (The selected tab gets a slightly different look.)
  2. Paint a themed border over the top of the provided tab page border. (I know this doesn't sound important, but the default border is not themed.)
  3. Repaint the bit of the selected tab that the border just drew over.

Points of Interest

I found that most people must have tried the .NET SDK way of painting the tabs and found it didn't work. They then proceeded to write their own tab controls, with all the problems of getting the design time experience just right, and so on. Although it took me a while to stumble across this solution, I think it is much cleaner (but then, I am biased in that respect). I retained the design time experience and the functionality of the underling .NET control, along with the speed gain to the application due to using the native control. And, I made it paint just the way I wanted.

The only part I failed to fully replicate from the VS 2005 IDE was that their selected tab seems to slightly overlap the tab to the left. Try as I might, I could not get that to work as the Paint event does not fire on that tab. I could paint the overlap fine, but it would not go away when I selected a different tab! However, my tabs were good enough for our purposes.

Also, I mentioned that I had a way to add the tab close and navigation buttons. You can paint stuff up there, but it won't respond to mouse events, at least not without writing your own mouse handling code! So, my solution was to make the custom tab control dynamically add these buttons to the containing control and manually position them over the top of the tab control at run time. Unfortunately, the docking and anchoring in .NET 2.0 doesn't work properly, or at least not in the way it did in 1.1, and so my nicely not docked, or anchored buttons would keep stretching and moving in response to events from the .NET docking manager! In the very controlled environment I created for our project, this was not a problem; however it's not the sort of flaky solution you want to publish.

History

  • 22/6/2006 - An update to this control. I have updated the VB code (C# will follow when I have time) to support the following new features:
    • The tabs now overlap properly on the left of the selected tab (thanks Bloggins).
    • The selected tab now paints its text in bold, just like the VS.NET tabs.
    • Images on the tabs are now supported.
    • If you set a tabpage to be Enabled = False, then the tab is not displayed with grey text and cannot be selected. Watch out, because, if you set the disabled tab to be the initial tab in the Forms Designer, then it will fail at run time. Also note that, TabPage.Enabled is a hidden property and can only be set in code (intellisense will never show it).
    • The background now paints better in design mode.
  • 19/2/2009 - An update to this control. I have updated the C# code to match the VB code. I have also implemented the font sizing fix suggested by martin.riepl.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

The Man from U.N.C.L.E.
Software Developer
United Kingdom United Kingdom
Unfortunately my real name was already in use as a code project login. For those of you who are wondering I am really Napoleon Solo. Sorry, I mean, Mark Jackson. Well, I do look a bit like him I think.

Comments and Discussions

 
Questioni want to create custom tab controls like TrapezoidalRight style. Pinmemberprabhu172-Jul-14 21:29 
QuestionMy Vote of 5 Pinmembersu myat1-May-13 7:29 
GeneralMy vote of 5 PinmemberMember 772676315-Dec-12 10:23 
QuestionItem sizei PinmemberMember 402480013-Dec-12 0:19 
SuggestionBorder PinmemberPaul van der Stel3-Aug-12 2:05 
QuestionVery Nice.... Still have a query Pinmembersvgharmode124-Feb-12 8:06 
GeneralMy vote of 5 PinmemberJames Jensen20-Feb-12 17:49 
GeneralMy vote of 5 Pinmember_Praetorian_4-Apr-11 6:38 
GeneralRepainting the previously selected tab [modified] PinmemberCheeso14-Apr-10 12:31 
GeneralRe: Repainting the previously selected tab PinmemberCheeso14-Apr-10 14:11 
GeneralRe: Repainting the previously selected tab PinmemberCheeso14-Apr-10 18:39 
GeneralRe: Source update now available PinmemberCheeso15-Apr-10 10:00 
NewsMajor update available PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:52 
GeneralPut the Custom TabControl into the VS toolbox PinmemberCheeso14-Apr-10 12:21 
GeneralAlignment Issue PinmemberMember 32092416-May-09 20:43 
NewsUpdate available PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:53 
GeneralThe tab switch buttons PinmemberA T I F5-Mar-09 8:53 
AnswerRe: The tab switch buttons PinmemberThe Man from U.N.C.L.E.5-Mar-09 23:03 
QuestionRe: The tab switch buttons PinmemberA T I F28-Mar-09 10:10 
AnswerRe: The tab switch buttons PinmemberThe Man from U.N.C.L.E.29-Mar-09 23:07 
GeneralRe: Putting the tab into the toolbox PinmemberCheeso14-Apr-10 12:21 
QuestionLocation Problem. PinmemberKrishna Kishore B14-Nov-08 21:40 
NewsUpdate available PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:53 
QuestionTab Size Pinmemberx31forest3-Sep-08 13:37 
AnswerRe: Tab Size PinmemberThe Man from U.N.C.L.E.3-Sep-08 23:24 
GeneralRe: Tab Size Pinmembermartin.riepl19-Feb-09 1:37 
GeneralRe: Tab Size PinmemberThe Man from U.N.C.L.E.19-Feb-09 2:04 
GeneralRe: Tab Size PinmemberThe Man from U.N.C.L.E.19-Feb-09 3:33 
GeneralRe: Tab Size PinmemberV# Guy30-Apr-09 20:46 
GeneralControlStyles.AllPaintingInWmPaint Pinmemberhell-citizen19-Aug-08 2:53 
GeneralVery Very Nice PinmemberMember 314412822-Jun-08 22:05 
GeneralVery Good. PinmemberMember 348579230-Jan-08 23:50 
Questionwhat about visual styles Pinmembergerykhan15-Jan-07 0:54 
AnswerRe: what about visual styles PinmemberThe Man from U.N.C.L.E.19-Feb-09 3:34 
QuestionAlignment? Pinmembergabegabe12-Jan-07 4:37 
AnswerRe: Alignment? Pinmemberlongdrver19-Dec-07 11:17 
AnswerMajor update available PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:54 
QuestionHow to make a gradient also inside the page? PinmemberNicola Costantini30-Oct-06 0:49 
QuestionTransparent background over a bitmap PinmemberEric Rasmussen27-Sep-06 8:05 
AnswerRe: Transparent background over a bitmap PinmemberRusty Adams11-Oct-06 5:24 
GeneralRe: Transparent background over a bitmap PinmemberEric Rasmussen13-Oct-06 12:38 
AnswerRe: Transparent background over a bitmap PinmemberMick Doherty29-Oct-06 2:00 
NewsMajor update PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:55 
GeneralMultiline Tab Control PinmemberIan Moores7-Sep-06 6:32 
QuestionNice Work! Commercial use? Pinmemberrobkinney10-Aug-06 11:22 
QuestionRe: Nice Work! Commercial use? [modified] Pinmemberrobkinney24-Oct-06 8:13 
AnswerRe: Nice Work! Commercial use? PinmemberThe Man from U.N.C.L.E.19-Feb-09 2:05 
NewsMajor Update PinmemberThe Man from U.N.C.L.E.23-Jul-10 10:55 
GeneralRespond to Image Events Pinmemberpcichanski7-Aug-06 10:41 
AnswerRe: Respond to Image Events PinmemberThe Man from U.N.C.L.E.7-Aug-06 11:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150129.1 | Last Updated 3 Jul 2010
Article Copyright 2006 by The Man from U.N.C.L.E.
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid