我想让我的TabControl上的选项卡显示在左侧或右侧。
但是,与System.Windows.Forms.TabControl不同,我希望文本保持水平,而不是被水平旋转90度或270度。在Winforms中使用水平文本的垂直制表符控制
虽然我可以编写代码来做到这一点我在大约一个小时或两个,我只是想我会先询问是否有任何现有的Winforms控件实现此功能。
注意:任何现有的解决方案应该最好是非商业的。
谢谢。
我想让我的TabControl上的选项卡显示在左侧或右侧。
但是,与System.Windows.Forms.TabControl不同,我希望文本保持水平,而不是被水平旋转90度或270度。在Winforms中使用水平文本的垂直制表符控制
虽然我可以编写代码来做到这一点我在大约一个小时或两个,我只是想我会先询问是否有任何现有的Winforms控件实现此功能。
注意:任何现有的解决方案应该最好是非商业的。
谢谢。
我不知道如何健壮,这是我不能声称已经创造了它,但... http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/
下面是做这件事的方式。
所以首先我们要改变其左对齐,通过设置属性:
对齐=左
如果您有XP主题开启,那么你可能会注意到选项卡的怪异布局控制。别担心,我们会好起来的。
正如您可能已经注意到标签是垂直的,并且我们的要求是水平的。所以我们可以改变标签的大小。但是我们可以做到这一点之前,我们必须设置SizeMode属性为,
SizeMode =固定
现在我们可以通过使用ItemSize属性更改大小,
ItemSize = 30,120 Width = 30 and Height = 120
在设置Alignment = Left之后,Tab控件旋转导致宽度和高度似乎颠倒的Tabs。这就是为什么当我们增加高度时,我们看到宽度在增加,当我们增加宽度时,高度就会受到影响。
现在文本也将显示,但垂直。不幸的是,没有简单的方法来解决这个问题。为此,我们必须自己写文本。要做到这一点,我们将首先设置DrawMode
DrawMode = OwnerDrawFixed
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.'s answer后的结果。
发行说明:
该代码可以从here下载。
谢谢亚历克斯。我一直认为它与你发布的截图类似,因此有兴趣查看代码,无论你分享的代码是否真的有帮助。 –
@AmitAndharia:我写了一个复制Visual Studio样式的代码,但不幸丢失了代码,所以我不得不修复这个代码并将它打包成一个'.vb'文件以供使用。如果你愿意,我可以重新实现VS风格的,但我不能保证很快得到它。 –
谢谢你,如果你可以做类似的事情,并分享,这将是gr8。 –
Microsoft提供了一个教程,用于使用现有的TabControl MSDN执行此操作,同时在C#和Visual Basic .NET中给出示例代码。他们的方法基于使用所有者绘图。下面总结他们的步骤:
的TabControl的的对准属性设置为右。
确保所有选项卡是相同的水平宽度通过设置SizeMode属性固定。
设置ItemSize属性为标签的首选大小,牢记宽度和高度颠倒。
设置DrawMode属性OwnerDrawFixed。
为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
值细末-tune你的标签外观无论你需要更炫的造型,我建议你看this other MSDN article为起点
(来源:How to: Display Side-Aligned Tabs with TabControl (MSDN))。
你读过[Rob P.的答案](http://stackoverflow.com/a/7501638)吗?在他发布他的答案近六年后,你已经重复了**完全相同的事情。 –
@AlexEssilfie我不会说完全一样的。首先,我提供的代码是用C#编写的,而他的代码是用VB.NET提供的。其次,我使用MSDN作为我的源代码,而不是从其他地方发布的论坛帖子,所以我想我提供的代码版本更可能代表接近这个的最佳实践。第三,如果你喜欢查看(使用'GetTabRect()'而不是'e.Bounds',代码来说明所选状态等),代码中就会有细微的差异。基本上,我发布了我的答案,因为我相信我必须分享的信息更完整,质量更高。 –
这是我非常喜欢的自定义选项卡控件的代码。您需要将此代码复制并粘贴到新类中,然后重新构建该项目。您会在工具箱中看到新的自定义用户控件。
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
感谢您的帮助。我稍微调整了一下代码,但没有从头开始写一个新的控件。 –
@AlexEssilfie是否让您看起来与您包含的截图完全相同?如果是这样,你可以分享代码吗? –
@AmitAndharia:我并不希望它完全如屏幕截图所示,但我能够很好地为它工作。为了更广泛的社区利益,我会在今天晚些时候或最多三天内上传我的代码。 –