2011-09-21 131 views
14

Me gustaría que las pestañas de mi TabControl se mostraran a la izquierda, o a veces a la derecha.
A diferencia de System.Windows.Forms.TabControl, sin embargo, me gustaría que el texto permanezca horizontal en lugar de girar 90 o 270 grados con respecto a la horizontal.Vertical Tab Control con texto horizontal en Winforms

Éstos son un par de fotografías que ilustran el concepto Vertical tabs in Visual Studio Vertical tabs in Firefox

Aunque podría escribir código para hacer esto mismo en aproximadamente una hora o dos, yo sólo pensé en preguntar primero si hay alguna existente Control de Winforms que implementa dicha característica.

NB: Cualquier solución existente debe ser preferiblemente no comercial.

Gracias.

Respuesta

21

No sé cómo esto es robusta y no puedo decir que han creado, pero ... http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/

Aquí está una manera de hacerlo.

Así que primero vamos a cambiar su alineación a la izquierda, estableciendo la propiedad:

alineación = Izquierda

Si tiene temas de XP encendidos entonces puede notar la extraña distribución de Tab Controlar. No te preocupes, lo haremos bien.

Como habrás notado, las pestañas son verticales y nuestro requisito es horizontal. Entonces podemos cambiar el tamaño de las pestañas. Pero antes de que podamos hacer esto tenemos que establecer la propiedad SizeMode como,

SizeMode = Fijo

Ahora podemos cambiar el tamaño utilizando la propiedad ItemSize,

ItemSize = 30, 120 Ancho = 30 y Altura = 120

Después de establecer Alineación = Izquierda, el control Tabulador gira las pestañas lo que hace que el Ancho y la Altura parezcan invertirse. Es por eso que cuando aumentamos la altura, vemos que el ancho está aumentando y cuando aumentamos el ancho, la altura se ve afectada.

Ahora el texto también se mostrará, pero verticalmente. Lamentablemente, no hay una forma simple de resolver este problema. Para este fin, tenemos que escribir el texto por nosotros mismos. Para ello vamos a definir en primer lugar el 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 
+0

Gracias por la ayuda.Modifiqué un poco el código, pero no fue tan largo como tomaría escribir un nuevo control desde cero. –

+0

@AlexEssilfie ¿Hiciste que se vea exactamente igual que las capturas de pantalla que has incluido? si es así, ¿puedes compartir el código? –

+0

@AmitAndharia: No deseaba que fuera exactamente como se muestra en las capturas de pantalla, pero pude hacer que funcionara lo suficientemente bien para mí. Subiré mi código más tarde o dentro de los tres días como máximo en interés de la comunidad en general. –

4

he decidido compartir el código que he desarrollado ya que algunas personas, como Amit Andharia, le gustaría beneficiarse de.

Este es el resultado después de haber implementado Rob P.'s answer.

Vertical Tabs Control screenshot

Notas de la versión:

  • diseño completo soporte en tiempo
  • Adaptación automática de fichas (hasta 128px de ancho)
  • iconos Tab implementadas
  • propiedades no utilizadas han sido oculto

El código se puede descargar desde here.

+0

Gracias Alex. En realidad, he estado pensando que sería similar a la captura de pantalla que publicaste y, por lo tanto, estaba interesado en ver el código; sin embargo, el código que compartiste es realmente útil. –

+1

@AmitAndharia: Escribí uno que reproduce el estilo de Visual Studio, pero desafortunadamente perdí ese código, así que tuve que repararlo y empacarlo en un archivo '.vb' para su uso. Si lo desea, podría volver a implementar el estilo VS, pero no puedo asegurar que lo obtenga muy pronto. –

+0

Gracias que sería gr8 si puede hacer algo similar y compartir. –

0

Hay un tutorial proporcionado por Microsoft para hacer esto con el TabControl existente en MSDN, con código de muestra en C# y Visual Basic .NET. Su método se basa en el uso del dibujo del propietario. Resumiendo sus pasos a continuación:

  1. Establecer alineación propiedad del TabControl a derecho.

  2. asegurar que todas las pestañas son de la misma anchura horizontal mediante el establecimiento de la propiedadSizeMode a fijo.

  3. Establecer la propiedadItemSize a su tamaño preferido para las pestañas, teniendo en cuenta que la anchura y la altura se invierten.

  4. Ajuste el DrawMode propiedad a OwnerDrawFixed.

  5. Configurar un controlador de eventos para DrawItem caso del TabControl, y coloque su código de dibujo propietario ahí dictar cómo se debe mostrar cada ficha. Su código de ejemplo de C# para el controlador de eventos se reproduce a continuación para mayor comodidad (se supone que su TabControl es nombrado 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)); 
    } 
    

es probable que pueda experimentar con su propiedad ItemSize y el valor _tabFont en el código anterior a fino -TUNE apariencia de las pestañas a todo lo que necesitas para estilizar aún más elegante, le recomiendo mirar this other MSDN article como punto de partida

(Fuente: How to: Display Side-Aligned Tabs with TabControl (MSDN))..

+0

¿Leyó [la respuesta de Rob P.] (http://stackoverflow.com/a/7501638)? Has repetido ** exactamente lo mismo ** casi seis años después de haber publicado su respuesta. –

+0

@AlexEssilfie No diría exactamente lo mismo. Primero, mi código provisto está en C#, mientras que el suyo fue provisto en VB.NET. En segundo lugar, estoy usando MSDN como mi fuente en lugar de una publicación en el foro de otra parte, así que me imagino que la versión del código que presento es más probable que represente las mejores prácticas para abordar esto. En tercer lugar, hay diferencias sutiles en el código si le interesa mirar (usando 'GetTabRect()' en lugar de 'e.Bounds', código para tener en cuenta los estados seleccionados, etc.). Básicamente, publiqué mi respuesta porque creía que la información que tenía que compartir era más completa y de mayor calidad. –

0

Este es el código para un control de pestañas personalizado que me gusta bastante. Deberá copiar y pegar este código en una nueva clase y luego reconstruir el proyecto. Verá un nuevo control de usuario personalizado en su caja de herramientas.

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 
Cuestiones relacionadas