65.9K
CodeProject is changing. Read more.
Home

MnemonicTabControl - a tabcontrol with accelerator key support

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.88/5 (7 votes)

Oct 19, 2005

2 min read

viewsIcon

80666

downloadIcon

546

An ownerdrawn tabcontrol supporting accelerator keys to switch between tabs.

Sample Image - MnemonicTabControl.gif

Introduction

This control is based on a post by Mona Shukla - Microsoft Developer Support on .NET 247, originally written in C# and described as a MnemonicTabControl. I've converted it to VB.NET and added several enhancements, such as a focus rectangle, HotTrack and disabled text and vertical tab alignment.

The Code

MnemonicTabControl inherits System.Windows.Forms.TabControl and overrides the ProcessMnemonic and OnDrawItem methods.

' Based on MnemonicTabControl class

' Original C# code posted by Mona Shukla - Microsoft Developer Support on .NET 247

' http://www.dotnet247.com/247reference/msgs/16/84624.aspx

' in microsoft.public.dotnet.framework.windowsforms


Public Class MnemonicTabControl
   Inherits System.Windows.Forms.TabControl

#Region " Windows Form Designer generated code "

   Public Sub New()
      MyBase.New()

      'This call is required by the Windows Form Designer.

      InitializeComponent()

      'Add any initialization after the InitializeComponent() call

      Me.DrawMode = TabDrawMode.OwnerDrawFixed

   End Sub

   'UserControl overrides dispose to clean up the component list.

   Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
      If disposing Then
         If Not (components Is Nothing) Then
            components.Dispose()
         End If
      End If
      MyBase.Dispose(disposing)
   End Sub

   'Required by the Windows Form Designer

   Private components As System.ComponentModel.IContainer

   'NOTE: The following procedure is required by the Windows Form Designer

   'It can be modified using the Windows Form Designer. 

   'Do not modify it using the code editor.

   <SYSTEM.DIAGNOSTICS.DEBUGGERSTEPTHROUGH()> Private Sub InitializeComponent()
      components = New System.ComponentModel.Container
   End Sub

#End Region

   Private Const selfoc As Integer = DrawItemState.Selected Or DrawItemState.Focus
   Private Const sel = DrawItemState.Selected
   Private Const notsf As Integer = Not (selfoc Or DrawItemState.Default)

   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 OnDrawItem(ByVal e As DrawItemEventArgs)
      MyBase.OnDrawItem(e)
      Dim g As Graphics = e.Graphics
      Dim rectf As RectangleF
      Dim vert As Boolean = (Me.Alignment > TabAlignment.Bottom)
      Dim off As Integer = 1 : If (e.State And sel) = sel Then off = -1
      Dim sf As New StringFormat(StringFormatFlags.NoClip _
                                 Or StringFormatFlags.NoWrap)
      With sf
         .HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show
         .Alignment = StringAlignment.Center
         .LineAlignment = StringAlignment.Center
      End With
      With e.Bounds
         If vert Then
            ' tabs are aligned left or right

            Dim m As New System.Drawing.Drawing2D.Matrix
            m.Translate(0, .Height - Me.TabPages(0).Top)
            m.RotateAt(270, New PointF(.X, .Y))
            g.Transform = m
            rectf = New RectangleF(.Left - Me.TabPages(0).Top, .Top + off, _
                                   .Height, .Width)
         Else
            ' tabs are aligned top or bottom

            rectf = New RectangleF(.X, .Y + off, .Width, .Height)
         End If
      End With
      Dim col As Color
      Select Case (e.State And notsf)
         Case DrawItemState.Disabled
            col = SystemColors.GrayText
         Case DrawItemState.HotLight
            col = SystemColors.HotTrack
         Case Else
            col = SystemColors.MenuText
      End Select
      g.DrawString(Me.TabPages(e.Index).Text, _
                   Me.Font, _
                   New SolidBrush(col), _
                   rectf, _
                   sf)
      If vert Then g.ResetTransform()
      If (e.State And selfoc) = selfoc Then
         ControlPaint.DrawFocusRectangle(g, _
                   [Rectangle].Inflate(e.Bounds, -1, -1))
      End If
      sf.Dispose()
   End Sub 'OnDrawItem


End Class 'MnemonicTabControl

Usage

Add one or more instances of MnemonicTabControl to your form. Set the HotTrack property to True, but leave the DrawMode as OwnerDrawFixed and the Appearance as Normal. The other properties may be set as needed. Then just use like a normal TabControl, add TabPages and other child controls. Use the ampersand symbol in the TabPage Text property to set the mnemonic (also called accelerator) key for the tab.

When running your app, you can press ALT plus the defined key(s) to switch between tabs. If you're a keyboard fanatic like me, this is a real plus!

Limitations

I've not included support for images as found in the default TabControl (hint: this would be a good challenge for somebody out there to enhance this control). The HotTrack feature uses the system's hot-tracking color defined in the system registry at the following key:

HKEY_CURRENT_USER\Control Panel\Colors

under the value HotTrackingColor. It's a string of three numbers separated by spaces. The RGB values range from 0-255. Mine is currently set to the string "0 70 213". If you're adventurous, you could edit MnemonicTabControl to add your own HotTrack color property.

Also, I'm cheating by using the fantastic visual support for XP provided by Skybound's VisualStyles control. If you don't have this free control in your collection, get it now! It is much easier and better than other means of achieving visual styles support for your app. It's free for use in both personal and commercial apps, but its use of unmanaged code will be a problem in partially trusted environments.

History

  • 19 Oct 2005 - Initial release.
  • 21 Oct 2005 - Revised code to correct orientation of vertical text (was top-down, now bottom-up to match .NET TabControl).