I am struggling to find way to color the tab headers of a tabpage in WinForms. There are solutions to color the current indexed tab using OnDrawItem event but can it be possible to color all the tabs with different colors at a time to make them intuitive for user for a certain behavior.
我正在努力寻找一种方法来在WinForms中为选项卡的页眉上色。有一些解决方案可以使用OnDrawItem事件给当前索引选项卡上色,但是否可以一次用不同的颜色给所有选项卡上色,以便用户对特定的行为感到直观。
Thanks in advance,
提前谢谢,
Rajeev Ranjan Lall
拉杰夫Ranjan拉尔
3 个解决方案
#1
25
Yes, there is no need for any win32 code. You just need to set the tab controls DrawMode property to 'OwnerDrawFixed' and then handle the tab control's DrawItem event.
是的,不需要任何win32代码。您只需将选项卡控件DrawMode属性设置为“OwnerDrawFixed”,然后处理选项卡控件的DrawItem事件。
The following code shows how:
下面的代码展示了如何:
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
// This event is called once for each tab button in your tab control
// First paint the background with a color based on the current tab
// e.Index is the index of the tab in the TabPages collection.
switch (e.Index )
{
case 0:
e.Graphics.FillRectangle(new SolidBrush(Color.Red), e.Bounds);
break;
case 1:
e.Graphics.FillRectangle(new SolidBrush(Color.Blue), e.Bounds);
break;
default:
break;
}
// Then draw the current tab button text
Rectangle paddedBounds=e.Bounds;
paddedBounds.Inflate(-2,-2);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.HighlightText, paddedBounds);
}
Setting the DrawMode to 'OwnerDrawnFixed' means each tab button has to be the same size (ie Fixed).
将DrawMode设置为“OwnerDrawnFixed”意味着每个选项卡按钮必须是相同的大小(即固定)。
However if you want to change the size of all tab buttons, you can set the tab control's SizeMode property to 'Fixed' and then change the ItemSize property.
但是,如果您想要更改所有选项卡按钮的大小,可以将选项卡控件的SizeMode属性设置为“Fixed”,然后更改ItemSize属性。
#2
40
An improved version of Ash's answer:
一个改进版的Ash的回答:
private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tabControl.TabPages[e.Index];
e.Graphics.FillRectangle(new SolidBrush(page.BackColor), e.Bounds);
Rectangle paddedBounds = e.Bounds;
int yOffset = (e.State == DrawItemState.Selected) ? -2 : 1;
paddedBounds.Offset(1, yOffset);
TextRenderer.DrawText(e.Graphics, page.Text, Font, paddedBounds, page.ForeColor);
}
This code uses the TextRenderer
class to draw its text (as .NET does), fixes problems with font clipping/wrapping by not negatively inflating the bounds, and takes tab selection into account.
这个代码使用TextRenderer类来绘制它的文本(如。net所做的),通过不带负面影响的边界来修复字体剪切/包装的问题,并考虑到选项卡的选择。
Thanks to Ash for the original code.
感谢Ash提供的原始代码。
#3
1
Using the current tab control, if it is possible you'd need to hook a lot of win-32 events (there may be a pre-wrapped implementation out there). Another alternative would be a 3rd-party tabbed control replacement; I'm sure plenty of vendors will sell you one.
使用当前选项卡控件,如果可能的话,您需要挂起许多win-32事件(可能有一个预先包装的实现)。另一种替代方案是由第三方提出的选项卡式控制替换方案;我肯定有很多商家会卖给你。
IMO, you might find it less pain to look at WPF; it is a big change, but has more control over things like this. You can host WPF inside winforms if needed (if you can't justify a full make-over, which is a pretty common reality).
在我看来,你可能会觉得看WPF不那么痛苦;这是一个巨大的变化,但对这类事情有更多的控制。如果需要的话,您可以在winforms中托管WPF(如果您不能证明完整的修改是合理的,这是一个非常常见的现实)。
#1
25
Yes, there is no need for any win32 code. You just need to set the tab controls DrawMode property to 'OwnerDrawFixed' and then handle the tab control's DrawItem event.
是的,不需要任何win32代码。您只需将选项卡控件DrawMode属性设置为“OwnerDrawFixed”,然后处理选项卡控件的DrawItem事件。
The following code shows how:
下面的代码展示了如何:
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
// This event is called once for each tab button in your tab control
// First paint the background with a color based on the current tab
// e.Index is the index of the tab in the TabPages collection.
switch (e.Index )
{
case 0:
e.Graphics.FillRectangle(new SolidBrush(Color.Red), e.Bounds);
break;
case 1:
e.Graphics.FillRectangle(new SolidBrush(Color.Blue), e.Bounds);
break;
default:
break;
}
// Then draw the current tab button text
Rectangle paddedBounds=e.Bounds;
paddedBounds.Inflate(-2,-2);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.HighlightText, paddedBounds);
}
Setting the DrawMode to 'OwnerDrawnFixed' means each tab button has to be the same size (ie Fixed).
将DrawMode设置为“OwnerDrawnFixed”意味着每个选项卡按钮必须是相同的大小(即固定)。
However if you want to change the size of all tab buttons, you can set the tab control's SizeMode property to 'Fixed' and then change the ItemSize property.
但是,如果您想要更改所有选项卡按钮的大小,可以将选项卡控件的SizeMode属性设置为“Fixed”,然后更改ItemSize属性。
#2
40
An improved version of Ash's answer:
一个改进版的Ash的回答:
private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tabControl.TabPages[e.Index];
e.Graphics.FillRectangle(new SolidBrush(page.BackColor), e.Bounds);
Rectangle paddedBounds = e.Bounds;
int yOffset = (e.State == DrawItemState.Selected) ? -2 : 1;
paddedBounds.Offset(1, yOffset);
TextRenderer.DrawText(e.Graphics, page.Text, Font, paddedBounds, page.ForeColor);
}
This code uses the TextRenderer
class to draw its text (as .NET does), fixes problems with font clipping/wrapping by not negatively inflating the bounds, and takes tab selection into account.
这个代码使用TextRenderer类来绘制它的文本(如。net所做的),通过不带负面影响的边界来修复字体剪切/包装的问题,并考虑到选项卡的选择。
Thanks to Ash for the original code.
感谢Ash提供的原始代码。
#3
1
Using the current tab control, if it is possible you'd need to hook a lot of win-32 events (there may be a pre-wrapped implementation out there). Another alternative would be a 3rd-party tabbed control replacement; I'm sure plenty of vendors will sell you one.
使用当前选项卡控件,如果可能的话,您需要挂起许多win-32事件(可能有一个预先包装的实现)。另一种替代方案是由第三方提出的选项卡式控制替换方案;我肯定有很多商家会卖给你。
IMO, you might find it less pain to look at WPF; it is a big change, but has more control over things like this. You can host WPF inside winforms if needed (if you can't justify a full make-over, which is a pretty common reality).
在我看来,你可能会觉得看WPF不那么痛苦;这是一个巨大的变化,但对这类事情有更多的控制。如果需要的话,您可以在winforms中托管WPF(如果您不能证明完整的修改是合理的,这是一个非常常见的现实)。