Click here to Skip to main content
11,638,173 members (75,449 online)
Click here to Skip to main content

TabStrip Control

, 30 May 2006 CPOL 188.5K 7.3K 286
Rate this:
Please Sign up or sign in to vote.
A flexible TabStrip control with basic design-time support.

Sample Image - tabstrips_demo.png

Introduction

With the introduction of .NET Framework 2.0, we have got a set of Strip controls, like MenuStrip and ToolStrip. They have rich design-time and run-time features and flexible interfaces. So the idea was to create a ToolStrip-like tab control supporting formatting in tab headers, animated icons, tab headers at any side, run-time tab reordering, tab grouping, and other stuff we miss in the Windows Forms TabControl.

Background

To implement the TabStrip and TabStripButton classes, we should use ToolStrip and ToolStripButton. Drawing should be performed via a ToolStripRenderer derived class - it's more flexible than painting in OnPaint. To use the current Windows XP theme, we ought to use methods from the System.Windows.Forms.VisualStyles namespace. The framework already wraps the uxTheme.dll, so we can go without a lot of P/Invoke calls.

We have to provide at least two ways for painting the interface: using visual styles, and without using them (we cannot use uxTheme on systems that don't support themes). So, let's add a theming check:

private bool useVS = Application.RenderWithVisualStyles;

/// <summary>
/// Returns if visual styles should be applied for drawing
/// <summary>
public bool UseVS
{
    get { return useVS; }
    set 
    {
        if (value && !Application.RenderWithVisualStyles)
            return;
        useVS = value; 
    }
}

ToolStrip generally has a few RenderModes: System, Professional, etc. So, if we want to paint an interface using any of them, we can either make derived classes from each Renderer class, or make one ToolStripRenderer derived class and use instances of the needed type within it. It will look like this:

private ToolStripRenderer currentRenderer = null;
private ToolStripRenderMode renderMode = ToolStripRenderMode.Custom;

/// <summary>
/// Gets or sets render mode for this renderer
/// </summary>
public ToolStripRenderMode RenderMode
{
    get { return renderMode; }
    set
    {
        renderMode = value;
        switch (renderMode)
        {
            case ToolStripRenderMode.Professional:
                currentRenderer = new ToolStripProfessionalRenderer();
                break;
            case ToolStripRenderMode.System:
                currentRenderer = new ToolStripSystemRenderer();
                break;
            default:
                currentRenderer = null;
                break;
        }
    }
}

Now, our toolbar's behavior should depend on its orientation. For this, we can use the ToolStrip.Orientation property. But it solves only one half of the problem. We still don't know at which side our TabStrip is docked. Theoretically, we can refer to the Dock and Parent properties to determine this, but in most cases, we know where our bar is located. So, we'll only make a property which determines if tab headers should be flipped.

private bool mirrored = false;

/// <summary>
/// Gets or sets whether to mirror background
/// </summary>
/// <remarks>Use false for left and top positions,
/// true for right and bottom</remarks>
public bool Mirrored
{
    get { return mirrored; }
    set { mirrored = value; }
}

The rest of the TabStripRenderer class is code for drawing, and nothing more interesting.

So we can go straight to the TabStripButton class. It extends the ToolStripButton with some new properties:

  • HotTextColor - Text color when mouse hovers TabStripButton.
  • SelectedTextColor - Text color when TabStripButton is SelectedTab.
  • SelectedFont - Font when TabStripButton is SelectedTab.
  • IsSelected - Gets or sets if tab is selected.

Also, we have to shadow the Checked, Padding, and Margin properties to avoid the user from breaking the pretty interface. These properties are also removed from the designer properties window.

Now, about the TabStrip class. It provides some new properties, most of them are wrappers for properties of the internal TabStripRenderer class.

  • UseVisualStyles - specifies if the system visual styles should be applied. If system does not support themes, this property is ignored, and the painting goes the custom way.
  • FlipButtons - specifies if the buttons should be drawn flipped. Set this to true if TabStrip should display tabs on the right or bottom side.
  • RenderStyle - property to use instead of RenderMode. Renderer and RenderMode are shadowed (for normal behavior), and removed from the designer property window.

Design-time support

First of all, we need to register TabStripButton as an available control for ToolStrip:

[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip)]
public class TabStripButton : ToolStripButton

Note that the class should be declared as public.

Designer view 1

Now, let's add the "Insert tab page" option in TabStrip's designer menu:

DesignerVerb insPage = null;

protected void InitControl()
{
    // ...
    // other initialization here
    // ...
    insPage = new DesignerVerb("Insert tab page", 
              new EventHandler(OnInsertPageClicked));
}

public override ISite Site
{
    get
    {
        ISite site = base.Site;
        if (site != null && site.DesignMode)
        {
            IContainer comp = site.Container;
            if (comp != null)
            {
                IDesignerHost host = comp as IDesignerHost;
                if (host != null)
                {
                    IDesigner designer = 
                       host.GetDesigner(site.Component);
                    if (designer != null && 
                          !designer.Verbs.Contains(insPage))
                        designer.Verbs.Add(insPage);
                }
            }
        }
        return site;
    }
    set
    {
        base.Site = value;
    }
}

protected void OnInsertPageClicked(object sender, EventArgs e)
{
    ISite site = base.Site;
    if (site != null && site.DesignMode)
    {
        IContainer container = site.Container;
        if (container != null)
        {
            TabStripButton btn = new TabStripButton();
            container.Add(btn);
            btn.Text = btn.Name;
        }
    }
}

The result looks like this:

Designer view 2

Summary

So, we have a new flexible control now. Unlike TabControl, it's not a container control, but it can be combined with other controls to simulate a container. And when tabs are needed for navigation, it leaves TabContol in the dust. And visual styles and rich picture support will make your application more cute and friendly.

History

  • 30.05.2006 - The very first version.

License

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

Share

About the Author

Messir
Web Developer
Russian Federation Russian Federation
Alex
.NET Developer
Russian Federation
rakemaker@gmail.com

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
whar27-Feb-12 8:37
memberwhar27-Feb-12 8:37 
QuestionGood job Pin
Mike Hankey29-Aug-11 12:31
memberMike Hankey29-Aug-11 12:31 
GeneralImprovement Pin
DominikF2-Dec-09 23:26
memberDominikF2-Dec-09 23:26 
GeneralC++ version Pin
Super Garrison7-Jul-09 8:32
memberSuper Garrison7-Jul-09 8:32 
GeneralRe: C++ version Pin
TheAdyDev24-Jan-15 4:12
memberTheAdyDev24-Jan-15 4:12 
GeneralLicensing Pin
Jacek Gajek1-Jul-09 4:53
memberJacek Gajek1-Jul-09 4:53 
Generalnice code, but has problem when I and a dropdownbutton Pin
chtoph10-May-09 17:04
memberchtoph10-May-09 17:04 
GeneralThanks a million Pin
StringDotEmpty22-Mar-09 20:11
memberStringDotEmpty22-Mar-09 20:11 
GeneralThanks a million Pin
Pankajkumar Nikam9-Feb-09 19:46
memberPankajkumar Nikam9-Feb-09 19:46 
GeneralNeed some help Pin
imresoft1-Jul-08 4:22
memberimresoft1-Jul-08 4:22 
QuestionBeautiful... someone can write the same in vb.net ? Pin
wakashich29-Mar-08 22:09
memberwakashich29-Mar-08 22:09 
AnswerRe: Beautiful... someone can write the same in vb.net ? Pin
The Dogcow Farmer25-Jun-08 10:38
memberThe Dogcow Farmer25-Jun-08 10:38 
GeneralClose button Pin
Giorgi Dalakishvili26-Dec-07 23:57
memberGiorgi Dalakishvili26-Dec-07 23:57 
GeneralRe: Close button Pin
Alpha Nerd7-May-08 0:22
memberAlpha Nerd7-May-08 0:22 
GeneralCtrl Tab Pin
Chris_McGrath23-Oct-07 18:56
memberChris_McGrath23-Oct-07 18:56 
Generalearth to Alex Pin
BillWoodruff5-May-07 9:14
memberBillWoodruff5-May-07 9:14 
GeneralTabStrip.Designer.cs not found in project Pin
Andrey Kaplun23-Apr-07 9:27
memberAndrey Kaplun23-Apr-07 9:27 
General'Messir.Windows.Forms.TabStrip' assembly Pin
Geert van Horrik22-Feb-07 5:50
memberGeert van Horrik22-Feb-07 5:50 
GeneralRe: 'Messir.Windows.Forms.TabStrip' assembly Pin
Geert van Horrik24-Feb-07 3:19
memberGeert van Horrik24-Feb-07 3:19 
GeneralDamn good code. [modified] Pin
sotona15-Feb-07 0:19
membersotona15-Feb-07 0:19 
GeneralLicensing Pin
Mattman20629-Jan-07 2:58
memberMattman20629-Jan-07 2:58 
QuestionBug? Pin
karrphoto11-Jan-07 19:34
memberkarrphoto11-Jan-07 19:34 
AnswerRe: Bug? Pin
ElasticLink9-Oct-07 23:51
memberElasticLink9-Oct-07 23:51 
Questioncombination with container control Pin
maorray11-Jan-07 3:10
membermaorray11-Jan-07 3:10 
GeneralGreat Pin
Zapper.Net16-Aug-06 1:12
memberZapper.Net16-Aug-06 1:12 
QuestionBackground color? Pin
krzychub3-Aug-06 23:10
memberkrzychub3-Aug-06 23:10 
GeneralGreat work, guy! Pin
Yuri Ovchinnikov17-Jun-06 4:36
memberYuri Ovchinnikov17-Jun-06 4:36 
Questionversion for .net 2003? Pin
netopeto9-Jun-06 7:07
membernetopeto9-Jun-06 7:07 
AnswerRe: version for .net 2003? Pin
Messir14-Jun-06 6:55
memberMessir14-Jun-06 6:55 
GeneralAnother Small Bug Pin
rsieiro9-Jun-06 6:21
memberrsieiro9-Jun-06 6:21 
GeneralRe: Another Small Bug Pin
Humble Programmer27-Jun-07 7:33
memberHumble Programmer27-Jun-07 7:33 
Generalsmall bug Pin
hominoid7-Jun-06 19:33
memberhominoid7-Jun-06 19:33 
GeneralRe: small bug Pin
Messir8-Jun-06 8:07
memberMessir8-Jun-06 8:07 
GeneralSuper Pin
k_savelev5-Jun-06 23:25
memberk_savelev5-Jun-06 23:25 
GeneralExcellent Work !!! Pin
Marcos Meli31-May-06 12:00
memberMarcos Meli31-May-06 12:00 

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
Web02 | 2.8.150728.1 | Last Updated 30 May 2006
Article Copyright 2006 by Messir
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid