ARTICLE

Creating a TabControl with XP-Look Style using Visual Studio 2005

Posted by Pankaj Patel Articles | Windows Controls April 10, 2006
The attached source code is a TabControl, in which I have applied the XP-Look style with hot key feature.
Download Files:
 
Reader Level:

 

Introduction

I had faced a big problem with the Tab Control included in Visual Studio 2005. So I applied "Mnemonic" (Hot key) feature in Tab Control, and for this reason I had set Draw Mode Property to OwnerDrawFixed But setting this property removed the XP-Look Style for the button.

 

So I tried to implement the Draw Item Event for Re-Draw buttons but it’s did not seem to work.

I even tried the "Sky Bound component" which is freely available on the net. But it did not match my requirement.

 

So, finally I decided to build my own Control. I browsed the internet for some resources concerning this, but I was not satisfied with what I found.

 

So here is the control, in which I have applied the XP-Look style with hot key feature.

 

Background

 

First of all, we need to set the double buffering technique to improve painting and to allow the control to change its appearance: 

Me.SetStyle(ControlStyles.UserPaint, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.DoubleBuffer, True)
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)

Then, you need to override the OnPaint event and draw your own control. The basic steps involved are:

Protected Overrides Function ProcessMnemonic(ByVal charCode As Char) As Boolean

    For Each p As TabPage In Me.TabPages

        If Control.IsMnemonic(charCode, p.Text) Then

            Me.SelectedTab = p

            Me.Focus()

            Return True

        End If

    Next p

    Return False

End Function 'ProcessMnemonic

 

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

    MyBase.OnPaint(e)

    DrawControl(e.Graphics)

End Sub

 

Friend Sub DrawControl(ByVal g As Graphics)

    If Not Visible Then

        Return

    End If

    Dim render As New VisualStyleRenderer(VisualStyleElement.Tab.Pane.Normal)

    Dim TabControlArea As Rectangle = Me.ClientRectangle

    Dim TabArea As Rectangle = Me.DisplayRectangle

    TabArea.Y = TabArea.Y + 1

    TabArea.Width = TabArea.Width + 1

    Dim nDelta As Integer = SystemInformation.Border3DSize.Width

    TabArea.Inflate(nDelta, nDelta)

    render.DrawBackground(g, TabArea)

    Dim i As Integer = 0

    While i < Me.TabCount

        DrawTab(g, Me.TabPages(i), i)

        i += 1

    End While

End Sub

 

Friend Sub DrawTab(ByVal g As Graphics, ByVal tabPage As TabPage, ByVal nIndex As Integer, ByVal nHoverIndex As Integer)

    Dim recBounds As Rectangle = Me.GetTabRect(nIndex)

    Dim tabTextArea As RectangleF = CType(Me.GetTabRect(nIndex), RectangleF)

    Dim bSelected As Boolean = (Me.SelectedIndex = nIndex)

    Dim render As New VisualStyleRenderer(VisualStyleElement.Tab.Pane.Normal)

    render = New VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Pressed)

    tabTextArea.Inflate(recBounds.X, recBounds.Y)

    Dim bHoverSelected As Boolean = (nIndex = nHoverIndex)

    If bSelected AndAlso bHoverSelected Then

        recBounds.Height = recBounds.Height + 10

        render = New VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Pressed)

        render.DrawBackground(g, recBounds)

        render.DrawEdge(g, recBounds, Edges.Diagonal, EdgeStyle.Sunken, EdgeEffects.Flat)

    ElseIf bHoverSelected AndAlso (Not bSelected) Then

        'recBounds.Height = recBounds.Height + 10

        recBounds.Y = recBounds.Y + 3

        recBounds.Height = recBounds.Height - 3

        tabTextArea.Offset(0, 2)

        render = New VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Pressed)

        render.DrawBackground(g, recBounds)

        render.DrawEdge(g, recBounds, Edges.Diagonal, EdgeStyle.Sunken, EdgeEffects.Flat)

    ElseIf bSelected Then

        recBounds.Height = recBounds.Height + 10

        render = New VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Pressed)

        render.DrawBackground(g, recBounds)

        render.DrawEdge(g, recBounds, Edges.Diagonal, EdgeStyle.Sunken, EdgeEffects.Flat)

    Else

        recBounds.Y = recBounds.Y + 3

        recBounds.Height = recBounds.Height - 3

        tabTextArea.Offset(0, 2)

        render = New VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Normal)

        render.DrawBackground(g, recBounds)

        render.DrawEdge(g, recBounds, Edges.Diagonal, EdgeStyle.Sunken, EdgeEffects.Flat)

    End If

    If (tabPage.ImageIndex >= 0) AndAlso (Not (ImageList Is Nothing)) AndAlso (Not (ImageList.Images(tabPage.ImageIndex) Is Nothing)) Then

        Dim nLeftMargin As Integer = 8

        Dim nRightMargin As Integer = 2

        Dim img As Image = ImageList.Images(tabPage.ImageIndex)

        Dim rimage As Rectangle = New Rectangle(recBounds.X + nLeftMargin, recBounds.Y + 1, img.Width, img.Height)

        Dim nAdj As Single = CType((nLeftMargin + img.Width + nRightMargin), Single)

        rimage.Y += (recBounds.Height - img.Height) / 2

        tabTextArea.X += nAdj

        tabTextArea.Width -= nAdj

        g.DrawImage(img, rimage)

    End If

    Dim stringFormat As StringFormat = New StringFormat

    stringFormat.Alignment = StringAlignment.Center

    stringFormat.LineAlignment = StringAlignment.Center

    If FlagControl Then

        stringFormat.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show

    Else

        stringFormat.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Hide

    End If

    Dim br As Brush

    br = New SolidBrush(tabPage.ForeColor)

    g.DrawString(tabPage.Text, Font, br, tabTextArea, stringFormat)

End Sub

 

Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)

    MyBase.OnMouseMove(e)

    Dim p As Point = e.Location

    For i As Integer = 0 To Me.TabCount - 1

        Dim r As Rectangle = GetTabRect(i)

        If r.Contains(p) Then

            hoverIndex = i

            Me.Invalidate()

        End If

    Next

End Sub

 

Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)

    MyBase.OnMouseLeave(e)

    hoverIndex = Me.SelectedIndex

    Me.Invalidate()

End Sub

 

Using the code

 

To use the code, simply add reference to the TabControl into the new project and drag TabControl in form.

 

History

  • 7th April, 2006: 1.0
    • First release.
  • 10th April, 2006: 1.1
    • Applied mouse hover functionality.

Note

Make your comments, corrections or requirements for credits. Your feedback is most welcome.

share this article :
post comment
 

Did you ever find a way to fix this error or a way around it.  Or even possibly a better way to do this?

Posted by Jake Apr 15, 2010

Very nice and thanks ...

But if you disable visual styles, returns this error:

Error during a transaction relating to visual styles. Nobody visual style active.

If you set Window Classic Style

For the rest I have to say ... really fantastic

Posted by pippo pippetto Nov 06, 2009

How can we create/Add Office Outlook TabControl Into VB2005 Form

Posted by Jaylem Chaudhari Mar 05, 2008

I use your idea, but I find a problem.

When I use (or desactive) No visual style (Classic Theme), the control is no usefull only when I active the Windows XP Theme.

How I implement  the "Application.RenderWithVisualStyles" validation for your code?

Some Idea?

Thanks, the code is good.

 

Adrian Garcia

Posted by Adrian Garcia Aug 29, 2006

The thing i was searching for, thanx.

Posted by Deepak Apr 10, 2006
Become a Sponsor
PREMIUM SPONSORS
  • ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications. Visit DynamicPDF here
    Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Team Foundation Server Hosting
Become a Sponsor