tabControl itemsize according to filename - c#

I please need assistance with tabcontrol itemsize. (winforms)
I have a owner-drawn tabcontrol and all working fine. Itemsize is set to width of 0 and sizemode to fixed in the tabcontrol properties. When I open a filename eg test.txt then "button" looks something like this
|test123.txt |
|Untitled |
which is fine, however, if I open longer filenames then the "button" looks like this
|thisisaverylongfilename.txt |
|anotherlongname.txt |
I'm trying to make the "button" so that the filename just fits with some space on the right and the space should be the same for all.
Below is my code for the user drawn tabcontrol
Image cross = imageList1.Images[0];
int xWidth = cross.Width;
TabPage tp = tabControl1.TabPages[e.Index];
Size size = tabControl1.ItemSize;
Font fntTab;
Brush bshBack;
Brush bshFore;
if (e.Index == this.tabControl1.SelectedIndex)
{
fntTab = new Font(FontFamily.GenericSansSerif, 8.0F, FontStyle.Regular);
bshBack = new System.Drawing.Drawing2D.LinearGradientBrush(e.Bounds, Color.FromName(tabpages_primary_backcolor), Color.FromName(tabpages_secondary_backcolor), System.Drawing.Drawing2D.LinearGradientMode.BackwardDiagonal);
bshFore = Brushes.Firebrick;
}
else
{
fntTab = new Font(FontFamily.GenericSansSerif, 8.0F, FontStyle.Regular);
bshBack = new SolidBrush(Color.Empty);
bshFore = new SolidBrush(Color.Black);
}
string tabName = this.tabControl1.TabPages[e.Index].Text;
StringFormat sftTab = new StringFormat();
e.Graphics.FillRectangle(bshBack, e.Bounds);
Rectangle recTab = e.Bounds;
recTab = new Rectangle(recTab.X + 5, recTab.Y + 4, recTab.Width, recTab.Height - 4);
e.Graphics.DrawString(tabName, fntTab, bshFore, recTab, sftTab);
if (tabControl1.SelectedTab != null)
{
currentCrossRect = new Rectangle(
e.Bounds.Left + size.Width - 22, 3, xWidth, xWidth);
e.Graphics.DrawImage(cross, currentCrossRect.X - 2, currentCrossRect.Y + 2);
}
Thanks and regards

Get the width of the text using:
SizeF s = e.Graphics.MeasureString(myString, myFont);
And then you can set the item's width to s.Width!

Related

C# Unable to dynamicly auto-size columns evenly in TableLayoutPanel

I have a WinForm that has a TableLayoutPanel control. My code will detect the number of attached monitors on screen, create a column per monitor, and then add a button for each display within each individual column in the TableLayoutControl so I can ensure that no matter how many monitors are attached, the buttons will appear "centered" across the form. One/two monitors renders just fine, however three monitors results in end columns not being evenly distributed.
Here is my code:
int count = Screen.AllScreens.Count();
this.monitorLayoutPanel.ColumnCount = count;
ColumnStyle cs = new ColumnStyle(SizeType.Percent, 100 / count);
this.monitorLayoutPanel.ColumnStyles.Add(cs);
this.monitorLayoutPanel.AutoSize = true;
var buttonSize = new Size(95, 75);
int z = 0;
foreach (var screen in Screen.AllScreens.OrderBy(i => i.Bounds.X))
{
Button monitor = new Button
{
Name = "Monitor" + screen,
AutoSize = true,
Size = buttonSize,
BackgroundImageLayout = ImageLayout.Stretch,
BackgroundImage = Properties.Resources.display_enabled,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font("Segoe UI", 10, FontStyle.Bold),
ForeColor = Color.White,
BackColor = Color.Transparent,
Text = screen.Bounds.Width + "x" + screen.Bounds.Height,
Anchor = System.Windows.Forms.AnchorStyles.None
};
this.monitorLayoutPanel.Controls.Add(monitor, z, 0);
z++;
monitor.MouseClick += new MouseEventHandler(monitor_Click);
}
I've tried making the buttons smaller, and increased the form size but the last column is always smaller than the first two. I can't understand it!
Clear ColumnStyles first.
this.monitorLayoutPanel.ColumnStyles.Clear();
then:
int count = Screen.AllScreens.Count();
for (int i = 0; i < count; i++)
{
ColumnStyle cs = new ColumnStyle(SizeType.Percent, (float)100 / count);
this.monitorLayoutPanel.ColumnStyles.Add(cs);
}
this.monitorLayoutPanel.AutoSize = true;
...
Reza Aghaei pointed me to this thread How to create a magic square using Windows Forms? which pointed me in the right direction. Updated (and working) code below. :)
int screens = Screen.AllScreens.Count();
this.monitorLayoutPanel.ColumnStyles.Clear();
this.monitorLayoutPanel.ColumnCount = screens;
this.monitorLayoutPanel.AutoSize = true;
int z = 0;
foreach (var screen in Screen.AllScreens.OrderBy(i => i.Bounds.X))
{
var percent = 100f / screens;
this.monitorLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, percent));
Button monitor = new Button
{
Name = "Monitor" + screen,
Size = new Size(95, 75),
BackgroundImageLayout = ImageLayout.Stretch,
BackgroundImage = Properties.Resources.display_enabled,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font("Segoe UI", 10, FontStyle.Bold),
ForeColor = Color.White,
BackColor = Color.Transparent,
Text = screen.Bounds.Width + "x" + screen.Bounds.Height,
Anchor = System.Windows.Forms.AnchorStyles.None
};
this.monitorLayoutPanel.Controls.Add(monitor, z, 0);
z++;
monitor.MouseClick += new MouseEventHandler(monitor_Click);

How to highlight search text in DataGridView?

I want to highlight the given search text in the DataGridView. I have tried cellFormatting event to find the bounds of the searchtext and draw FillRectangle, but i could not exactly get the bounds of the search text.
In the added image, i have tried to highlight text "o" but it highlights other characters also.
Could anyone share me how to draw perfect rectangle to highlight the searched text.
Regards,
Amal Raj.
You need to use the CellPainiting event. Try this code:
string keyValue = "Co"; //search text
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.Value == null) return;
StringFormat sf = StringFormat.GenericTypographic;
sf.FormatFlags = sf.FormatFlags | StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.DisplayFormatControl;
e.PaintBackground(e.CellBounds, true);
SolidBrush br = new SolidBrush(Color.White);
if (((int)e.State & (int)DataGridViewElementStates.Selected) == 0)
br.Color = Color.Black;
string text = e.Value.ToString();
SizeF textSize = e.Graphics.MeasureString(text, Font, e.CellBounds.Width, sf);
int keyPos = text.IndexOf(keyValue, StringComparison.OrdinalIgnoreCase);
if (keyPos >= 0)
{
SizeF textMetricSize = new SizeF(0, 0);
if (keyPos >= 1)
{
string textMetric = text.Substring(0, keyPos);
textMetricSize = e.Graphics.MeasureString(textMetric, Font, e.CellBounds.Width, sf);
}
SizeF keySize = e.Graphics.MeasureString(text.Substring(keyPos, keyValue.Length), Font, e.CellBounds.Width, sf);
float left = e.CellBounds.Left + (keyPos <= 0 ? 0 : textMetricSize.Width) + 2;
RectangleF keyRect = new RectangleF(left, e.CellBounds.Top + 1, keySize.Width, e.CellBounds.Height - 2);
var fillBrush = new SolidBrush(Color.Yellow);
e.Graphics.FillRectangle(fillBrush, keyRect);
fillBrush.Dispose();
}
e.Graphics.DrawString(text, Font, br, new PointF(e.CellBounds.Left + 2, e.CellBounds.Top + (e.CellBounds.Height - textSize.Height) / 2), sf);
e.Handled = true;
br.Dispose();
}

ListView drawsubitem - column is not selected

Why the 4`th column is not selected? I use listView3_DrawSubItem and e.DrawDefault = true; for that column and now is not selectable.
Edit:
The listView1_DrawSubItem code:
// Only interested in 2nd column.
if (e.Header != this.action)
{
e.DrawDefault = true;
return;
}
drawItem(e);
And the drawitem code:
string drawString = e.SubItem.Text;
float size = 8.25F;
e.DrawBackground();
Bitmap image = new Bitmap(DesktopCleaner.Properties.Resources.folder_icon_512x512);
if (drawString == "Leave on Desktop")
{
image = new Bitmap(DesktopCleaner.Properties.Resources.desk);
}
else if (drawString == "Recycle")
{
image = new Bitmap(DesktopCleaner.Properties.Resources.recyclebin_preview_1);
}
else if (drawString == "Delete")
{
image = new Bitmap(DesktopCleaner.Properties.Resources.free_vector_delete_icon_101805_Delete_icon);
}
var imageRect = new Rectangle(e.Bounds.X + 3, e.Bounds.Y, image.Width - 2, image.Height - 2);
e.Graphics.DrawImage(image, imageRect);
System.Drawing.Font drawFont = new System.Drawing.Font(listView1.Font.FontFamily, size, FontStyle.Bold);
System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
var strrect = new Rectangle(e.Bounds.X + 18, e.Bounds.Y + 3, 150, e.Bounds.Height);
e.Graphics.DrawString(drawString, drawFont, drawBrush, strrect, drawFormat);
You are responsible for drawing the selection.
So even if you use the nice methods:
e.DrawBackground();
e.DrawText();
no selection is being drawn.
So you need to use FillRectangle and DrawString with the appropriate Colors, maybe like this:
bool selected = e.Item.Selected;
using ( SolidBrush backBrush = new SolidBrush(
selected? SystemColors.MenuHighlight :SystemColors.Window ) )
e.Graphics.FillRectangle(backBrush, e.Bounds);
using (SolidBrush textBrush = new SolidBrush(
selected ? Color.White : Color.Black ))
e.Graphics.DrawString(e.Item.Text, yourFont, textBrush, e.Bounds.X, e.Bounds.Y);
The code is simplified; you'll use your coodinates to make room for the icons etc..

Showing a part of a brush on a Stackpanel

I want to show a brush on my stackpanel in the following behavior:
Brush is an image 240x120
panel is 240x60
I want to show a part of the brush like rect(0, 30, 240, 60) (so that the image on the panel is moved down a bit)
tried it with viewport and Viewbox with no result (empty Panel)
This is my code:
for (int i = 0; i < listExplorationData.Count; i++)
{
StackPanel panelLoop = new StackPanel();
panelLoop.Name = "panel_" + i.ToString();
panelLoop.Width = 240;
panelLoop.Height = 60;
panelLoop.Margin = new Thickness(0, 60 * i, 0, 0);
BitmapImage image = new BitmapImage(
new Uri("pack://application:,,,/GW2-MyWorldExploration;component/Images/" +
listExplorationData[i].mapname_en.Replace(" ", "_") +
"_loading_screen.jpg"));
ImageBrush brush = new ImageBrush();
brush.ImageSource = image;
brush.Stretch = Stretch.None;
brush.Viewport = new Rect(0, 30, 240, 60);
panelLoop.Background = brush;
mainStackPanel.Children.Add(panelLoop);
}
In order to show part of the ImageBrush you would have to set the Viewbox. If you want to specify the viewbox in absolute units, you would also have to set the ViewboxUnits property:
brush.ViewboxUnits = BrushMappingMode.Absolute;
brush.Viewbox = new Rect(0, 30, 240, 60);

Vertical Tab Control with horizontal text in Winforms

I would like to have the tabs on my TabControl displayed on the left, or sometimes right.
Unlike the System.Windows.Forms.TabControl, however, I would like the text to remain horizontal instead of being rotated by 90 or 270 degrees to the horizontal.
Here are a couple of pictures illustrating the concept
Though I could write code to do this myself in about an hour or two, I just thought I'd ask first if there is any existing Winforms control that implements such feature.
NB: Any existing solution should preferably be non-commercial.
Thanks.
I don't know how robust this is and I can't claim to have created it but...
http://www.dreamincode.net/forums/topic/125792-how-to-make-vertical-tabs/
Here's a way of doing it.
So first we are going to change its alignment to Left, by setting the property:
Alignment = Left
If you have XP themes turned on then you may notice the weird layout of Tab Control. Don't worry we will make it fine.
As you may have noticed that Tabs are vertical, and our requirement is horizontal. So we can change the size of Tabs. But before we can do this we have to set the SizeMode property as,
SizeMode = Fixed
Now we can change the size by using the ItemSize property,
ItemSize = 30, 120
Width = 30 and Height = 120
After setting the Alignment = Left, Tab control rotates the Tabs which causes the Width and Height seem to be reversed. That is why when we increase Height, we see that width is increasing and when we increase width the height is effected.
Now Text will also be displaying, but vertically. Unfortunately there is no simple way to resolve this issue. For this purpose we have to write the Text by ourselves. To do this we will first set the 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
This is the code for a custom tab control that I'm quite fond of. You will need to copy and paste this code into a new class then rebuild the project. You will see a new custom user control displayed in your toolbox.
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
This is an old question but I found a good looking C# class. After adding the normal WinForms tab control. Add this to your project as a class E.G DotNetBarTabControl.cs Then make sure to replace the Winforms tab controls to this class.
this.tabControl1 = new System.Windows.Forms.TabControl();
must be changed to:
this.tabControl1 = new TabControls.DotNetBarTabControl();
private System.Windows.Forms.TabControl tabControl1;
must be changed to:
private TabControls.DotNetBarTabControl tabControl1;
DotNetBarTabControl.cs Class:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
// thanks to Mavamaarten~ for coding this
namespace TabControls
{
internal class DotNetBarTabControl : TabControl
{
public DotNetBarTabControl()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint |
ControlStyles.DoubleBuffer, true);
SizeMode = TabSizeMode.Fixed;
ItemSize = new Size(44, 136);
Alignment = TabAlignment.Left;
SelectedIndex = 0;
}
protected override void OnPaint(PaintEventArgs e)
{
Bitmap b = new Bitmap(Width, Height);
Graphics g = Graphics.FromImage(b);
if (!DesignMode)
SelectedTab.BackColor = SystemColors.Control;
g.Clear(SystemColors.Control);
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(ItemSize.Height + 3, 0),
new Point(ItemSize.Height + 3, 999));
g.DrawLine(new Pen(Color.FromArgb(170, 187, 204)), new Point(0, Size.Height - 1),
new Point(Width + 3, Size.Height - 1));
for (int i = 0; i <= TabCount - 1; i++)
{
if (i == SelectedIndex)
{
Rectangle x2 = new Rectangle(new Point(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2),
new Size(GetTabRect(i).Width + 3, GetTabRect(i).Height - 1));
ColorBlend myBlend = new ColorBlend();
myBlend.Colors = new Color[] { Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240) };
myBlend.Positions = new float[] { 0f, 0.5f, 1f };
LinearGradientBrush lgBrush = new LinearGradientBrush(x2, Color.Black, Color.Black, 90f);
lgBrush.InterpolationColors = myBlend;
g.FillRectangle(lgBrush, x2);
g.DrawRectangle(new Pen(Color.FromArgb(170, 187, 204)), x2);
g.SmoothingMode = SmoothingMode.HighQuality;
Point[] p =
{
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(SystemBrushes.Control, p);
g.DrawPolygon(new Pen(Color.FromArgb(170, 187, 204)), p);
if (ImageList != null)
{
try
{
g.DrawImage(ImageList.Images[TabPages[i].ImageIndex],
new Point(x2.Location.X + 8, x2.Location.Y + 6));
g.DrawString(" " + TabPages[i].Text, Font, Brushes.Black, x2, new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
catch (Exception)
{
g.DrawString(TabPages[i].Text, new Font(Font.FontFamily, Font.Size, FontStyle.Bold),
Brushes.Black, x2, new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
}
else
{
g.DrawString(TabPages[i].Text, new Font(Font.FontFamily, Font.Size, FontStyle.Bold),
Brushes.Black, x2, new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
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
{
Rectangle x2 = 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 != null)
{
try
{
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
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
catch (Exception)
{
g.DrawString(TabPages[i].Text, Font, Brushes.DimGray, x2, new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
}
else
{
g.DrawString(TabPages[i].Text, Font, Brushes.DimGray, x2, new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
});
}
}
}
e.Graphics.DrawImage(b, new Point(0, 0));
g.Dispose();
b.Dispose();
}
}
}
You can have fun making a dark theme to. In the photo Form2 uses the material skin. It can be found on NuGet as well.
I have decided to share the code I developed since some people, such as Amit Andharia, would like to benefit from it.
This is the result after I had implemented Rob P.'s answer.
Release Notes:
Full design time support
Automatic resizing of tabs (up to 128px wide)
Tab icons implemented
Unused properties have been hidden
The code can be downloaded from here.
There is a tutorial provided by Microsoft for doing this with the existing TabControl on MSDN, with sample code given in both C# and Visual Basic .NET. Their method is based on using owner drawing. Summarizing their steps below:
Set the TabControl's Alignment property to Right.
Ensure all tabs are the same horizontal width by setting the SizeMode property to Fixed.
Set the ItemSize property to your preferred size for the tabs, keeping in mind that the width and height are reversed.
Set the DrawMode property to OwnerDrawFixed.
Set up an event handler for the TabControl's DrawItem event, and place your owner drawing code in there dictating how each tab should be displayed. Their C# sample code for the event handler is reproduced below for convenience (it assumes your TabControl is named 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));
}
You can probably experiment with your ItemSize property and the _tabFont value from the above code to fine-tune your tabs' appearance to whatever you need. For even fancier styling, I'd recommend looking at this other MSDN article as a starting point.
(Source: How to: Display Side-Aligned Tabs with TabControl (MSDN))

Categories