Controllo scheda verticale con testo orizzontale in Winforms

Mi piacerebbe avere le tabs sul mio TabControl visualizzate a sinistra, oa volte a destra.
A differenza di System.Windows.Forms.TabControl, tuttavia, vorrei che il testo rimanga orizzontale anziché ruotato di 90 o 270 gradi rispetto all’orizzontale.

Ecco un paio di immagini che illustrano il concetto Vertical tabs in Visual Studio Schede verticali in Firefox

Anche se potrei scrivere codice per farlo da solo in circa un’ora o due, ho pensato di chiedere prima se esiste un controllo Winforms esistente che implementa tale funzione.

NB: qualsiasi soluzione esistente dovrebbe preferibilmente essere non commerciale.

Grazie.

Non so quanto sia robusto e non posso affermare di averlo creato ma … http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/

Ecco un modo per farlo.

Quindi per prima cosa cambieremo il suo allineamento a Sinistra, impostando la proprietà:

Allineamento = Sinistra

Se hai temi XP triggersti, potresti notare lo strano layout di Tab Control. Non ti preoccupare, lo faremo bene.

Come avrai notato, le tabs sono verticali e il nostro requisito è orizzontale. Quindi possiamo cambiare la dimensione delle tabs. Ma prima di farlo, dobbiamo impostare la proprietà SizeMode come,

SizeMode = Fixed

Ora possiamo cambiare la dimensione usando la proprietà ItemSize,

ItemSize = 30, 120 Width = 30 e Height = 120

Dopo aver impostato l’allineamento = Sinistra, il controllo Tab fa ruotare le Tab che fanno in modo che la larghezza e l’altezza sembrino invertite. Ecco perché quando aumentiamo l’altezza, vediamo che la larghezza aumenta e quando aumentiamo la larghezza viene effettuata l’altezza.

Ora verrà visualizzato anche il testo, ma in verticale. Sfortunatamente non esiste un modo semplice per risolvere questo problema. Per questo scopo dobbiamo scrivere il testo da soli. Per fare ciò, impostiamo prima 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 

Ho deciso di condividere il codice che ho sviluppato dal momento che alcune persone, come Amit Andharia , vorrebbero beneficiarne.

Questo è il risultato dopo aver implementato la risposta di Rob P ..

Vertical Tabs Control screenshot

Note di rilascio:

  • Supporto completo per il tempo di progettazione
  • Ridimensionamento automatico delle tabs (fino a 128 px di larghezza)
  • Icone di tabulazione implementate
  • Le proprietà non utilizzate sono state nascoste

Il codice può essere scaricato da qui .

Questo è il codice per un controllo tabulazioni personalizzato a cui sono molto affezionato. Dovrai copiare e incollare questo codice in una nuova class, quindi ribuild il progetto. Verrà visualizzato un nuovo controllo utente personalizzato visualizzato nella casella degli strumenti.

Controllo scheda verticale con indicatore e 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 

Esiste un tutorial fornito da Microsoft per fare ciò con il TabControl esistente su MSDN , con codice di esempio fornito in C # e Visual Basic .NET. Il loro metodo si basa sull’utilizzo del disegno del proprietario. Riassumendo i loro passi di seguito:

  1. Impostare la proprietà Alignment di TabControl su Right .

  2. Assicurarsi che tutte le tabs abbiano la stessa larghezza orizzontale impostando la proprietà SizeMode su Fixed .

  3. Impostare la proprietà ItemSize sulla dimensione preferita per le tabs, tenendo presente che la larghezza e l’altezza sono invertite .

  4. Impostare la proprietà DrawMode su OwnerDrawFixed .

  5. Impostare un gestore di eventi per l’evento DrawItem di TabControl e inserire il codice di disegno del proprietario in cui è necessario dettare la visualizzazione di ciascuna scheda. Il codice di esempio C # per il gestore eventi è riprodotto qui di seguito per comodità (presuppone che TabControl sia denominato 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)); } 

Probabilmente puoi sperimentare con la proprietà ItemSize e il valore _tabFont dal codice precedente per perfezionare l’aspetto delle tabs in base alle tue esigenze. Per uno stile ancora più elaborato, ti consiglio di guardare questo altro articolo di MSDN come punto di partenza.

(Fonte: come: visualizzare tabs con allineamento laterale con TabControl (MSDN) )