Элемент управления вертикальной вкладкой с горизонтальным текстом в Winforms - PullRequest
15 голосов
/ 21 сентября 2011

Я бы хотел, чтобы вкладки на моем TabControl отображались слева или иногда справа.
Однако, в отличие от System.Windows.Forms.TabControl, я бы хотел, чтобы текст оставался горизонтальным, а не поворачивался на 90 или 270 градусов к горизонтали.

Вот пара фотографий, иллюстрирующих концепцию Vertical tabs in Visual Studio Vertical tabs in Firefox

Хотя я мог написать код, чтобы сделать это сам, примерно через час или два, я просто подумал, что сначала спрошу, существует ли какой-либо существующий элемент управления Winforms, реализующий такую ​​функцию.

Примечание: Любое существующее решение предпочтительно должно быть некоммерческим.

Спасибо.

Ответы [ 4 ]

22 голосов
/ 21 сентября 2011

Я не знаю, насколько это надежно, и я не могу утверждать, что создал его, но ... http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/

Вот способ сделать это.

Итак, сначала мы собираемся изменить его выравнивание по левому краю, установив свойство:

Выравнивание = Левый

Если у вас включены темы XP, то вы можете заметить странный макет Tab Control. Не волнуйтесь, у нас все получится.

Как вы могли заметить, вкладки расположены вертикально, а наше требование - горизонтальное. Таким образом, мы можем изменить размер вкладок. Но прежде чем мы сможем это сделать, мы должны установить свойство SizeMode как

SizeMode = Fixed

Теперь мы можем изменить размер, используя свойство ItemSize,

ItemSize = 30, 120 Ширина = 30 и Высота = 120

После установки Alignment = Left элемент управления 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
4 голосов
/ 27 ноября 2014

Я решил поделиться кодом, который я разработал, поскольку некоторые люди, такие как Амит Андхария , хотели бы извлечь из этого пользу.

Это результат после того, как я реализовал Ответ Роба П. .

Vertical Tabs Control screenshot

Примечания к выпуску:

  • Полная поддержка времени разработки
  • Автоматическое изменение размера вкладок (шириной до 128 пикселей)
  • Реализация значков вкладок
  • Неиспользуемые свойства были скрыты

Код можно загрузить с здесь .

1 голос
/ 24 августа 2017

Это код для пользовательского элемента управления вкладками, который мне очень нравится.Вам нужно будет скопировать и вставить этот код в новый класс, а затем пересобрать проект.Вы увидите новый пользовательский элемент управления, отображаемый на панели инструментов.

Vertical Tab Control with Indicator and 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
1 голос
/ 03 мая 2017

Microsoft предоставляет учебное пособие для этого с существующим TabControl на MSDN , с примером кода, приведенным как в C #, так и в Visual Basic .NET.Их метод основан на использовании рисунка владельца.Обобщая их шаги ниже:

  1. Установите для свойства Выравнивание TabControl значение Вправо .

  2. Убедитесьвсе вкладки имеют одинаковую горизонтальную ширину, установив для свойства SizeMode значение Фиксированный .

  3. Установите для свойства ItemSize значениепредпочитаемый вами размер вкладок, учитывая, что ширина и высота меняются местами .

  4. Установите для свойства DrawMode значение OwnerDrawFixed .

  5. Установите обработчик события для события DrawItem TabControl и поместите туда свой чертежный код владельца, определяющий способ отображения каждой вкладки.Их пример кода 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) )

...