Управление вертикальной вкладкой с горизонтальным текстом в Winforms
Я бы хотел, чтобы вкладки на моем TabControl отображались слева или иногда правильно.
Однако, в отличие от System.Windows.Forms.TabControl, я бы хотел, чтобы текст оставался горизонтальным вместо поворота на 90 или 270 градусов по горизонтали.
Вот пара фотографий, иллюстрирующих концепцию
![Vertical tabs in Visual Studio Vertical tabs in Visual Studio]()
![Vertical tabs in Firefox]()
Хотя я мог написать код, чтобы сделать это сам примерно через час или два, я просто подумал, что сначала спрошу, есть ли какой-либо существующий элемент управления Winforms, который реализует такую функцию.
NB: Любое существующее решение должно быть предпочтительно некоммерческим.
Спасибо.
Ответы
Ответ 1
Я не знаю, насколько это здорово, и я не могу утверждать, что создал его, но...
http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/
Вот как это сделать.
Итак, сначала мы изменим его выравнивание налево, установив свойство:
Выравнивание = левый
Если у вас включены темы XP, вы можете заметить странный макет Tab Control. Не беспокойтесь, мы сделаем это хорошо.
Как вы могли заметить, что вкладки вертикальные, а наше требование - горизонтальное. Таким образом, мы можем изменить размер вкладок. Но прежде чем мы сможем сделать это, мы должны установить свойство SizeMode как,
SizeMode = Исправлено
Теперь мы можем изменить размер с помощью свойства ItemSize,
ItemSize = 30, 120
Ширина = 30 и Высота = 120
После установки выравнивания = Влево, элемент управления Tab поворачивает вкладки, из-за которых ширина и высота кажутся противоположными. Поэтому, когда мы увеличиваем высоту, мы видим, что ширина увеличивается, и когда мы увеличиваем ширину, выполняется высота.
Теперь текст будет отображаться, но вертикально. К сожалению, нет простого способа решить эту проблему. Для этого мы должны сами написать текст. Для этого мы сначала установим 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
Ответ 2
Я решил поделиться кодом, который я разработал, поскольку некоторые люди, такие как Amit Andharia, хотели бы извлечь из этого выгоду.
Это результат после того, как я внедрил Rob P. answer.
![VerticalTabsControl screenshot Vertical Tabs Control screenshot]()
Примечания к выпуску:
- Полная поддержка времени разработки
- Автоматическое изменение размеров вкладок (до 128 пикселей в ширину)
- Значки вкладки реализованы
- Неиспользуемые свойства были скрыты
Код можно скачать с здесь.
Ответ 3
Существует учебник, предоставленный Microsoft для этого с существующим TabControl на MSDN, с образцом кода, указанным как в С#, так и в Visual Basic.NET. Их метод основан на использовании чертежа владельца. Подводя следующие шаги:
-
Установите свойство TabControl Выравнивание в Вправо.
-
Убедитесь, что все вкладки имеют одинаковую ширину горизонтали, установив для свойства SizeMode значение Исправлено.
-
Задайте свойство ItemSize для вашего предпочтительного размера для вкладок, имея в виду, что ширина и высота меняются на противоположные.
-
Установите для свойства DrawMode значение OwnerDrawFixed.
-
Настройте обработчик событий для события TabControl DrawItem и поместите в него код чертежа владельца, определяющий, как должна отображаться каждая вкладка. Их пример кода С# для обработчика событий воспроизводится ниже для удобства (предполагается, что ваш 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))
Ответ 4
Это код для настраиваемого элемента управления вкладки, который мне очень нравится. Вам нужно будет скопировать и вставить этот код в новый класс, а затем перестроить проект. Вы увидите новый пользовательский элемент управления, отображаемый в панели инструментов.
![Управление вертикальной вкладкой с индикатором и 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