Winforms中带有水平文本的垂直制表符控件

我希望我的TabControl上的标签显示在左侧,有时是右侧。
但是,与System.Windows.Forms.TabControl不同,我希望文本保持水平而不是向水平方向旋转90度或270度。

这里有几张图片说明了这个概念 Vertical tabs in Visual Studio Firefox中的垂直选项卡

虽然我可以在大约一两个小时内自己编写代码来执行此操作,但我只是想我会先询问是否存在实现此类function的Winforms控件。

注意:任何现有的解决方案最好是非商业性的。

谢谢。

我不知道这是多么强大,我不能声称已创建它但是…… http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/

这是一种做法。

首先,我们将通过设置属性将其对齐方式更改为Left:

对齐=左

如果您打开了XP主题,那么您可能会注意到Tab Control的奇怪布局。 别担心,我们会把它变好。

您可能已经注意到Tabs是垂直的,我们的要求是水平的。 所以我们可以改变Tabs的大小。 但在我们能够做到这一点之前,我们必须将SizeMode属性设置为,

SizeMode =固定

现在我们可以使用ItemSize属性更改大小,

ItemSize = 30,120宽度= 30,高度= 120

设置Alignment = Left后,Tab控件旋转Tabs,导致Width和Height似乎相反。 这就是为什么当我们增加高度时,我们看到宽度增加,当我们增加宽度时,高度会受到影响。

现在Text也将显示,但是垂直显示。 不幸的是,没有简单的方法来解决这个问题。 为此,我们必须自己编写文本。 为此,我们将首先设置DrawMode

DrawMode = OwnerDrawFixed

01

Private Sub TabControl1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles TabControl1.DrawItem Dim g As Graphics Dim sText As String Dim iX As Integer Dim iY As Integer Dim sizeText As SizeF Dim ctlTab As TabControl ctlTab = CType(sender, TabControl) g = e.Graphics sText = ctlTab.TabPages(e.Index).Text sizeText = g.MeasureString(sText, ctlTab.Font) iX = e.Bounds.Left + 6 iY = e.Bounds.Top + (e.Bounds.Height - sizeText.Height) / 2 g.DrawString(sText, ctlTab.Font, Brushes.Black, iX, iY) End Sub 

我决定分享我开发的代码,因为有些人,比如Amit Andharia ,希望从中受益。

这是我实施Rob P.的答案之后的结果 。

Vertical Tabs Control screenshot

发行说明:

  • 完整的设计时间支持
  • 标签的自动resize(最大128px宽)
  • 实施标签图标
  • 未使用的属性已被隐藏

代码可以从这里下载。

这是我非常喜欢的自定义选项卡控件的代码。 您需要将此代码复制并粘贴到新类中,然后重建项目。 您将在工具箱中看到一个新的自定义用户控件。

带指示器和ImageList的垂直选项卡控件

  Imports System.Drawing.Drawing2D Class DotNetBarTabcontrol Inherits TabControl Sub New() SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True) DoubleBuffered = True SizeMode = TabSizeMode.Fixed ItemSize = New Size(44, 136) End Sub Protected Overrides Sub CreateHandle() MyBase.CreateHandle() Alignment = TabAlignment.Left End Sub Function ToPen(ByVal color As Color) As Pen Return New Pen(color) End Function Function ToBrush(ByVal color As Color) As Brush Return New SolidBrush(color) End Function Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) Dim B As New Bitmap(Width, Height) Dim G As Graphics = Graphics.FromImage(B) Try : SelectedTab.BackColor = Color.White : Catch : End Try G.Clear(Color.White) G.FillRectangle(New SolidBrush(Color.FromArgb(246, 248, 252)), New Rectangle(0, 0, ItemSize.Height + 4, Height)) 'G.DrawLine(New Pen(Color.FromArgb(170, 187, 204)), New Point(Width - 1, 0), New Point(Width - 1, Height - 1)) 'comment out to get rid of the borders 'G.DrawLine(New Pen(Color.FromArgb(170, 187, 204)), New Point(ItemSize.Height + 1, 0), New Point(Width - 1, 0)) 'comment out to get rid of the borders 'G.DrawLine(New Pen(Color.FromArgb(170, 187, 204)), New Point(ItemSize.Height + 3, Height - 1), New Point(Width - 1, Height - 1)) 'comment out to get rid of the borders G.DrawLine(New Pen(Color.FromArgb(170, 187, 204)), New Point(ItemSize.Height + 3, 0), New Point(ItemSize.Height + 3, 999)) For i = 0 To TabCount - 1 If i = SelectedIndex Then Dim x2 As Rectangle = New Rectangle(New Point(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2), New Size(GetTabRect(i).Width + 3, GetTabRect(i).Height - 1)) Dim myBlend As New ColorBlend() myBlend.Colors = {Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240)} myBlend.Positions = {0.0F, 0.5F, 1.0F} Dim lgBrush As New LinearGradientBrush(x2, Color.Black, Color.Black, 90.0F) lgBrush.InterpolationColors = myBlend G.FillRectangle(lgBrush, x2) G.DrawRectangle(New Pen(Color.FromArgb(170, 187, 204)), x2) G.SmoothingMode = SmoothingMode.HighQuality Dim p() As Point = {New Point(ItemSize.Height - 3, GetTabRect(i).Location.Y + 20), New Point(ItemSize.Height + 4, GetTabRect(i).Location.Y + 14), New Point(ItemSize.Height + 4, GetTabRect(i).Location.Y + 27)} G.FillPolygon(Brushes.White, p) G.DrawPolygon(New Pen(Color.FromArgb(170, 187, 204)), p) If ImageList IsNot Nothing Then Try If ImageList.Images(TabPages(i).ImageIndex) IsNot Nothing Then G.DrawImage(ImageList.Images(TabPages(i).ImageIndex), New Point(x2.Location.X + 8, x2.Location.Y + 6)) G.DrawString(" " & TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) Else G.DrawString(TabPages(i).Text, New Font(Font.FontFamily, Font.Size, FontStyle.Bold), Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End If Catch ex As Exception G.DrawString(TabPages(i).Text, New Font(Font.FontFamily, Font.Size, FontStyle.Bold), Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End Try Else G.DrawString(TabPages(i).Text, New Font(Font.FontFamily, Font.Size, FontStyle.Bold), Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End If G.DrawLine(New Pen(Color.FromArgb(200, 200, 250)), New Point(x2.Location.X - 1, x2.Location.Y - 1), New Point(x2.Location.X, x2.Location.Y)) G.DrawLine(New Pen(Color.FromArgb(200, 200, 250)), New Point(x2.Location.X - 1, x2.Bottom - 1), New Point(x2.Location.X, x2.Bottom)) Else Dim x2 As Rectangle = New Rectangle(New Point(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2), New Size(GetTabRect(i).Width + 3, GetTabRect(i).Height + 1)) G.FillRectangle(New SolidBrush(Color.FromArgb(246, 248, 252)), x2) G.DrawLine(New Pen(Color.FromArgb(170, 187, 204)), New Point(x2.Right, x2.Top), New Point(x2.Right, x2.Bottom)) If ImageList IsNot Nothing Then Try If ImageList.Images(TabPages(i).ImageIndex) IsNot Nothing Then G.DrawImage(ImageList.Images(TabPages(i).ImageIndex), New Point(x2.Location.X + 8, x2.Location.Y + 6)) G.DrawString(" " & TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) Else G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End If Catch ex As Exception G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End Try Else G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}) End If End If Next e.Graphics.DrawImage(B.Clone, 0, 0) G.Dispose() : B.Dispose() End Sub End Class 

Microsoft提供了一个教程,用于在MSDN上使用现有的TabControl进行此操作,并在C#和Visual Basic .NET中提供示例代码。 他们的方法基于使用所有者绘图。 总结他们的步骤如下:

  1. 将TabControl的Alignment属性设置为Right

  2. 通过将SizeMode属性设置为Fixed,确保所有选项卡的水平宽度相同。

  3. ItemSize属性设置为选项卡的首选大小,请记住宽度和高度是相反的

  4. DrawMode属性设置为OwnerDrawFixed

  5. 为TabControl的DrawItem事件设置事件处理程序,并将所有者绘图代码放在那里,指示每个选项卡应如何显示。 为方便起见,下面重现了它们的事件处理程序的C#示例代码(假设您的TabControl名为tabControl1

     private void tabControl1_DrawItem(Object sender, System.Windows.Forms.DrawItemEventArgs e) { Graphics g = e.Graphics; Brush _textBrush; // Get the item from the collection. TabPage _tabPage = tabControl1.TabPages[e.Index]; // Get the real bounds for the tab rectangle. Rectangle _tabBounds = tabControl1.GetTabRect(e.Index); if (e.State == DrawItemState.Selected) { // Draw a different background color, and don't paint a focus rectangle. _textBrush = new SolidBrush(Color.Red); g.FillRectangle(Brushes.Gray, e.Bounds); } else { _textBrush = new System.Drawing.SolidBrush(e.ForeColor); e.DrawBackground(); } // Use our own font. Font _tabFont = new Font("Arial", (float)10.0, FontStyle.Bold, GraphicsUnit.Pixel); // Draw string. Center the text. StringFormat _stringFlags = new StringFormat(); _stringFlags.Alignment = StringAlignment.Center; _stringFlags.LineAlignment = StringAlignment.Center; g.DrawString(_tabPage.Text, _tabFont, _textBrush, _tabBounds, new StringFormat(_stringFlags)); } 

您可以尝试使用上面代码中的ItemSize属性和_tabFont值来微调选项卡的外观以满足您的需要。 对于更漂亮的造型,我建议将这篇其他MSDN文章作为起点。

(来源: 如何:使用TabControl(MSDN)显示侧面对齐的选项卡 )