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

WinForms Tab Control with properly drawn bottom tabs

By , 4 Mar 2013
 

Using UxTabControl

Introduction

Most developers face the same problem when using a tab control with a tab alignment other than Top: when visual styles are enabled, the tabs are drawn incorrectly (to say more precisely - in top orientation only). The same thing happened to me one day. I had a task to convert an old .NET 1.1 application to run under .NET Framework 2.0. I wanted to add visual styles support, and oops - we have a known tab problem. I had been searching the web and had found some solutions, but none of them satisfied me fully. I decided to write my own control UxTabControl by subclassing System.Windows.Forms.TabControl.

You might find my control useful because I think many of you still use Windows Forms and not WPF, and Microsoft hasn't added correct tab drawing for SysTabControl32 even in Windows 8. Those guys just require only the top tabs for you to get your application Microsoft certified (by the way, Apple has implemented their tabs correctly in any orientation from stock; you know what I mean if you used Interface Builder deep enough at least once).

Background

I've used the Adi DEDIC article here on CodeProject as a starting point so you can read the Background section from there. Adi explains how to rotate tabs and draw them. My control uses a similar technique. But Adi's control is written in C++ and uses MFC, mine is written mostly in managed code though it uses some platform interops. I have also used some tips about the tab scroller from Mick Doherty's site. You can find the bottom tab control there also in his implementation, but without the source code.

Using the Code

The simplest way of using the control is to add it to your toolbox. To do this, just right-click on the preferred section of the toolbox and then select "Choose items..." in the popped up menu; click "Browse" in the ".NET Framework Components" tab and look for UxTabControl.dll. You're done! Now, you should see UxTabControl in your toolbox, and you can drag it on your form like any other control.

If you don't want to use it in the way described above for some reasons (you aren't using Visual Studio but Notepad and command prompt, for example), you have to add UxTabControl.dll to your project reference libraries. After that, in the code where you are planning to use the control, add the following directive:

using VSControls;

Or in Visual Basic:

Imports VSControls

Now, you can create and manipulate UxTabControl the same way as System.Windows.Forms.TabControl

UxTabControl myControl = new UxTabControl();
myControl.Location = new Point(10, 10);
//other code you need

In Visual Basic:

Dim myControl As New UxTabControl
myControl.Location = New Point(10, 10)
'other code you need

All projects and solutions are generated with Visual Studio 2012 and .NET Framework 4.0 Client Profile. If you don't happen to have Professional or more advanced edition of the IDE available, you can download express edition for Windows desktop from the Microsoft website.

Requirements & Limitations

  • .NET Framework 4.0 or newer is required to run the code. Still, after certain modifications, I believe that it's possible to compile the code with older versions of the framework, but not older than 2.0.
  • Custom drawing is not guaranteed to work properly with visual styles other than Microsoft's ones.
  • Supported Windows systems: Vista, 7, 8 and corresponding server versions. Of course, visual styles must be enabled; otherwise, drawing will be done by the default Windows engine (that's the way I've designed it).
  • Left and right tab alignments aren't supported. I suppose it is not very convenient for a user to lean the head towards the shoulder for a tab's caption to be read, don't you think so? But, if you badly need that feature, you can implement it by yourself.

Points of Interest

  • This article shows how you can subclass some standard .NET controls and override some properties to reach the desired effect.
  • You will learn how to use the System.Windows.Forms.VisualStyles namespace to draw parts of some controls (tab control, in our case).
  • Also, the code shows how to override WndProc to react on some Windows messages.

History

  • 20.03.2009 - Version 1.0
  • 7.03.2010 - Version 1.0.1
    • Fixed bug with tab text (thanks to SierraMike for reporting). Now text is drawn by GDI instead of GDI+ (I found the solution for "memory bitmap + TextRenderer + ClearType enabled" problem) and so it fits inside tabs
  • 22.02.2013 - Version 1.0.2
    • The control now has a sort of a "transparent" background, i.e., it draws its parent's background on its surface before drawing itself.
    • The RightToLeft and RightToLeftLayout properties are no longer disabled. They were disabled in previous versions due to painting problems.
    • The control has been renamed to UxTabControl (after uxtheme.dll). The previous name was bound to a particular version of Windows and that is not quite accurate.
    • The support for Windows XP and 2003 has been dropped. I consider these operating systems obsolete.

License

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

About the Author

VUnreal
Team Leader Scand Ltd.
Belarus Belarus
Member
I've have been programming since 1998. I started from command line applications written in Express Pascal 2.0 under CP-M. In 2002 I learned C++ and was programming using Borland C++ Builder. In 2005 I discovered .NET for myself. I did some occasional Java programming as well. In the end, it's not a language or a technology that matters, it's how you use it. Currently I'm doing Web development.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionSide TabsmemberJalapeno Bob5 Mar '13 - 6:54 
My predecessor implemented a very messy window with tabs along the side that selected which book of top tabs should be displayed. Some of those top tabs have a second row of top tabs. Every time I look at it, I thank God that I have not had to modify it. Inevitably, any modification will break it. Heck, even recompiling it might break it!
 
It works with Windows 7. Will it work with Windows 8? Probably, but I do not know. Thankfully, planning to convert to Windows 8 probably will not occur this year. Will a requirement change cause me to have to modify this mess? Very probably, somewhere in the (hopefully, very far) future. Redesigning this window is politically a non-starter - the Training Department would never agree because of the retraining costs. To be honest, I have not had the courage (or the time) to even look at the source code for this mess.
 
It would be great for my peace of mind if your tab control would provide a complete solution to side tabs as well as top and bottom tabs.
 
Jalapeno Bob
Lord, grant me the serenity to accept that there are some things I just can’t keep up with, the determination to keep up with the things I must keep up with, and the wisdom to find a good RSS feed from someone who keeps up with what I’d like to, but just don’t have the damn bandwidth to handle right now.
© 2009, Rex Hammock
 

GeneralMy vote of 5memberrspercy6523 Feb '13 - 14:03 
This is Nice...I like it.
5 radio buttons for you.
QuestionNice onememberwmjordan22 Feb '13 - 22:41 
It is still working with either customized (hacked) visual styles, or visual styles disabled, on XP. Please don't drop the support. There are still quite a lot of people around using XP or 2003.
 
However, the tabs are flickering while the mouse is moving around them. Maybe it came from the "transparent background" code. Did you encounter the same issue with an old PC and a cheap slow video adapter?
AnswerRe: Nice onememberVUnreal24 Feb '13 - 9:14 
I suspect the flickering comes from the removal of OptimizedDoubleBuffer style. But if it's present, then RTL layout doesn't work properly, it draws weird black lines of unknown origin. Regarding XP systems, I'm no longer going to test on them. But if you say it still works for you, well, you're lucky then.
lifecycle of a lifecycle of a lifecycle

GeneralRe: Nice one [modified]memberwmjordan26 Feb '13 - 21:34 
Thank you very much for the reply.
I don't need the RTL layout and I have added the following line to the constructor of the UxTabControl.
The flickering was eliminated.
this.SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
 
I also changed the targeting framework to 2.0 and it compiled quite well.
No need to modify any line of code.

modified 27 Feb '13 - 3:43.

GeneralThats great!groupvlad7817 Jun '11 - 9:22 
Can i use tab control without programing the point? I just thinking of using buttons and groupBoxes to switch between the groupboxes. However, goupboxes don't work when they are over lapped.
MySignature.BringToFront();

AnswerRe: Thats great!memberVUnreal8 Jun '11 - 10:09 
Did I get you right: you want to emulate tab control using group boxes and buttons? Set group boxes text to empty, put them in a stack, and then change their Z-order by calling BringToFront/SendToBack. But don't mix them up: you must remember which one you're about to bring to foreground. If they're not working (like you're claiming) then use panels. They should work. In case you need a border badly, you can use one group box with empty text. Just put a stack of panels inside of it (make them small enough so that they don't overlap the border of the group box).
GeneralRe: Thats great!groupvlad7818 Jun '11 - 18:14 
This sounds good, however i found an actual tab control tool in the toolbox of C#, this made regular tabs, at the top, but that is fine.
MySignature.BringToFront();

GeneralRe: Thats great!memberVUnreal12 Jun '11 - 11:14 
So you just didn't find tab control on the toolbox initially, did you? And that's why you wanted to emulate it? I tell you this: if tabs on top are OK for you, then standard tab control will do just fine.
GeneralRe: Thats great!groupvlad78113 Jun '11 - 15:51 
yes you are right.
MySignature.BringToFront();

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 4 Mar 2013
Article Copyright 2009 by VUnreal
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid