Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleUse a TabControl with owner-drawn tabs in Visual Basic .NET
DescriptionThis example shows how to use a TabControl with owner-drawn tabs in Visual Basic .NET.
KeywordsTabControl, OwnerDraw, owner drawn, tab, control, DrawMode, OwnerDrawFixed, VB.NET
CategoriesControls, VB.NET
 
To make an owner drawn tab control, the code sets the control's DrawMode property to OwnerDrawFixed. The SizeMode must be Fixed if the program needs to change the tab size. This example does change the size to 10 pixels wide and 6 pixels taller than the initial default.
 
' Set OwnerDraw mode.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal _
     e As
System.EventArgs) Handles MyBase.Load
    ' We will draw the tabs.
    TabControl1.DrawMode = TabDrawMode.OwnerDrawFixed

    ' SizeMode must be Fixed to change tab size.
    TabControl1.SizeMode = TabSizeMode.Fixed

    ' Set the size for the tabs.
    Dim tab_size As Size = TabControl1.ItemSize
    tab_size.Width = 100
    tab_size.Height += 6
    TabControl1.ItemSize = tab_size
End Sub
 
When the control needs to draw a tab, it raises its DrawItem event handler. This routine gets the tab's area by using the control's GetTabRect method. This returns a rectangle slightly different from the one in the e.Bounds parameter and is the rectangle that we can use later in the MouseDown event handler.

DrawItem then checks the e.State parameter to see whether the tab is selected and picks colors accordingly. It fills the tab's background and, if the tab is selected, it draws a focus rectangle on it.

Next the code makes a rectangle representing the tab's area minus some margins. It uses this rectangle to position the tab number in the upper left corner and the tab's text centered. The program then draws an X in the upper right corner.

 
' Draw a tab.
Private Sub TabControl1_DrawItem(ByVal sender As Object, _
     ByVal e As
System.Windows.Forms.DrawItemEventArgs) Handles _
    TabControl1.DrawItem
    Dim txt_brush As Brush
    Dim box_brush As Brush
    Dim box_pen As Pen

    ' We draw in the TabRect rather than on e.Bounds
    ' so we can use TabRect later in MouseDown.
    Dim tab_rect As Rectangle = _
        TabControl1.GetTabRect(e.Index)

    ' Draw the background.
    ' Pick appropriate pens and brushes.
    If e.State = DrawItemState.Selected Then
        e.Graphics.FillRectangle(Brushes.DarkOrange, _
            tab_rect)
        e.DrawFocusRectangle()

        txt_brush = Brushes.Yellow
        box_brush = Brushes.Silver
        box_pen = Pens.DarkBlue
    Else
        e.Graphics.FillRectangle(Brushes.PaleGreen, _
            tab_rect)

        txt_brush = Brushes.DarkBlue
        box_brush = Brushes.LightGray
        box_pen = Pens.DarkBlue
    End If

    ' Allow room for margins.
    Dim layout_rect As New RectangleF( _
        tab_rect.Left + TAB_MARGIN, _
        tab_rect.Y + TAB_MARGIN, _
        tab_rect.Width - 2 * TAB_MARGIN, _
        tab_rect.Height - 2 * TAB_MARGIN)
    Dim string_format As New StringFormat

    ' Draw the tab # in the upper left corner.
    Dim small_font As New Font(Me.Font.FontFamily, 6, _
        FontStyle.Bold)
    string_format.Alignment = StringAlignment.Near
    string_format.LineAlignment = StringAlignment.Near
    e.Graphics.DrawString( _
        e.Index.ToString(), _
        small_font, _
        txt_brush, _
        layout_rect, _
        string_format)

    ' Draw the tab's text centered.
    Dim big_font As New Font(Me.Font, FontStyle.Bold)
    string_format.Alignment = StringAlignment.Center
    string_format.LineAlignment = StringAlignment.Center
    e.Graphics.DrawString( _
        TabControl1.TabPages(e.Index).Text, _
        big_font, _
        txt_brush, _
        layout_rect, _
        string_format)

    ' Draw an X in the upper right corner.
    Dim rect As Rectangle = TabControl1.GetTabRect(e.Index)
    e.Graphics.FillRectangle(box_brush, _
        layout_rect.Right - m_Xwid, _
        layout_rect.Top, _
        m_Xwid, _
        m_Xwid)
    e.Graphics.DrawRectangle(box_pen, _
        layout_rect.Right - m_Xwid, _
        layout_rect.Top, _
        m_Xwid, _
        m_Xwid)
    e.Graphics.DrawLine(box_pen, _
        layout_rect.Right - m_Xwid, _
        layout_rect.Top, _
        layout_rect.Right, _
        layout_rect.Top + m_Xwid)
    e.Graphics.DrawLine(box_pen, _
        layout_rect.Right - m_Xwid, _
        layout_rect.Top + m_Xwid, _
        layout_rect.Right, _
        layout_rect.Top)

    ' Clean up. (Don't Dispose the stock pens and brushes.)
    string_format.Dispose()
End Sub
 
When the user clicks on a tab, the program determines whether the mouse is over any tab's X. If the mouse is over an X, the program removes the corresponding tab.
 
Private Sub TabControl1_MouseDown(ByVal sender As Object, _
     ByVal e As
System.Windows.Forms.MouseEventArgs) Handles _
    TabControl1.MouseDown
    ' See if this is over a tab.
    For i As Integer = 0 To TabControl1.TabPages.Count - 1
        ' Get the TabRect plus room for margins.
        Dim tab_rect As Rectangle = _
            TabControl1.GetTabRect(i)
        Dim rect As New RectangleF( _
            tab_rect.Left + TAB_MARGIN, _
            tab_rect.Y + TAB_MARGIN, _
            tab_rect.Width - 2 * TAB_MARGIN, _
            tab_rect.Height - 2 * TAB_MARGIN)
        If e.X >= rect.Right -  m_Xwid AndAlso _
           e.X <= rect.Right AndAlso _
           e.Y >= rect.Top AndAlso _
           e.Y <= rect.Top + m_Xwid _
        Then
            Debug.WriteLine("Tab " & i)
            TabControl1.TabPages.RemoveAt(i)
            Exit Sub
        End If
    Next i
End Sub
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated