在我向 tabControl1 添加自定义背景色后,我的 tabControl1 不会显示其 DrawImage
My tabControl1 wont show its DrawImage after I added custom backcolor to my tabControl1
我不太确定我哪里出错了,但在我将自定义背景色添加到我的 tabControl1 之前一切正常,我看到其他选项卡上的 X 和添加选项卡的 +
添加此代码源后,我添加的选项卡不存在了,但 + 按钮功能和其他选项卡功能也让我觉得 backColor 只是将它们隐藏在后面。
SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
e.Graphics.FillRectangle(backColor, rec);
有没有什么方法可以让标签页完全显示我用背景颜色放入的 DrawItem?
代码来源:
private void tabControl1_DrawItem_1(object sender, DrawItemEventArgs e)
{
Rectangle rec = tabControl1.ClientRectangle;
SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
e.Graphics.FillRectangle(backColor, rec);
StringFormat StrFormat = new StringFormat();
StrFormat.LineAlignment = StringAlignment.Center;
StrFormat.Alignment = StringAlignment.Center;
Brush bshBack = new SolidBrush(Color.FromArgb(55, 55, 55)); // change tab color
var tabPage = this.tabControl1.TabPages[e.Index];
var tabRect = this.tabControl1.GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
if (e.Index == this.tabControl1.TabCount - 1)
{
// Add
var addImage = Properties.Resources.Add;
e.Graphics.FillRectangle(bshBack, e.Bounds);
e.Graphics.DrawImage(addImage,
tabRect.Left + (tabRect.Width - addImage.Width) / 2,
tabRect.Top + (tabRect.Height - addImage.Height) / 2);
}
else
{
// Close
var closeImage = Properties.Resources.Close;
e.Graphics.FillRectangle(bshBack, e.Bounds);
e.Graphics.DrawImage(closeImage,
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font,
tabRect, tabPage.ForeColor, TextFormatFlags.Left);
}
}
扩展 解决方案。新建一个class并继承TabControl
,在构造函数中设置如下所示的控件样式,主要是按照你想要的方式绘制控件和选项卡。
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
namespace YourProjectNamespace
{
[DesignerCategory("Code")]
[ToolboxBitmap(typeof(TabControl))]
public class TabControlEx : TabControl
{
public TabControlEx() : base()
{
SetStyle(ControlStyles.AllPaintingInWmPaint
| ControlStyles.ResizeRedraw
| ControlStyles.OptimizedDoubleBuffer
| ControlStyles.UserPaint, true);
UpdateStyles();
Padding = new Point(14, 4);
}
private Color backColor = Color.FromArgb(40, 40, 40);
/// <inheritdoc cref="Control.BackColor"/>
[DefaultValue(typeof(Color), "40, 40, 40"),
Browsable(true),
EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new Color BackColor
{
get => backColor;
set
{
if (backColor != value)
{
backColor = value;
Invalidate();
}
}
}
private Image addImage;
[DefaultValue(null)]
public Image AddButtonImage
{
get => addImage;
set
{
addImage = value;
Invalidate();
}
}
private Image closeImage;
[DefaultValue(null)]
public Image CloseButtonImage
{
get => closeImage;
set
{
closeImage = value;
Invalidate();
}
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
SendMessage(Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
if (TabCount > 0) TabPages[TabCount - 1].Text = "";
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.Clear(BackColor);
if (TabCount == 0) return;
for (int i = 0; i < TabCount; i++)
{
var tp = TabPages[i];
var r = Rectangle.Inflate(GetTabRect(i), -4, 0);
if (i == TabCount - 1)
{
if (AddButtonImage != null)
g.DrawImage(AddButtonImage,
r.X + (r.Width - AddButtonImage.Width) / 2,
r.Y + (r.Height - AddButtonImage.Height) / 2,
AddButtonImage.Width, AddButtonImage.Height);
}
else
{
if (i == SelectedIndex)
using (var brSel = new SolidBrush(Color.FromArgb(105, 105, 105)))
g.FillRectangle(brSel, Rectangle.Inflate(r, 4, 1));
if (ImageList != null && tp.ImageIndex >= 0)
ImageList.Draw(g,
r.X, r.Y + (r.Height - ImageList.ImageSize.Height) / 2,
tp.ImageIndex);
if (CloseButtonImage != null)
{
var closeRect = new Rectangle(new Point(
r.Right - CloseButtonImage.Width,
r.Y + (r.Height - CloseButtonImage.Height) / 2),
CloseButtonImage.Size);
g.DrawImage(CloseButtonImage, closeRect,
0, 0, CloseButtonImage.Width, CloseButtonImage.Height,
GraphicsUnit.Pixel);
}
TextRenderer.DrawText(g, tp.Text, tp.Font, r, Color.White,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter);
}
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
var lastIndex = TabCount - 1;
if (GetTabRect(lastIndex).Contains(e.Location))
{
var args = new AddingTabEventArgs();
OnAddingTab(args);
if (args.Cancel) return;
var newTp = new TabPage
{
Text = "New Tab",
BackColor = BackColor
};
TabPages.Insert(lastIndex, newTp);
SelectedIndex = lastIndex;
}
else
{
for (var i = 0; i < TabPages.Count; i++)
{
var r = Rectangle.Inflate(GetTabRect(i), -4, 0);
if (new Rectangle(r.Right - 16, r.Y + (r.Height - 16), 16, 16)
.Contains(e.Location))
{
var args = new ClosingTabEventArgs(TabPages[i]);
OnClosingTab(args);
if (args.Cancel) return;
TabPages[i].Dispose();
break;
}
}
}
}
protected override void OnSelecting(TabControlCancelEventArgs e)
{
if (e.TabPageIndex == TabCount - 1)
e.Cancel = true;
else
base.OnSelecting(e);
}
public event EventHandler<ClosingTabEventArgs> ClosingTab;
protected virtual void OnClosingTab(ClosingTabEventArgs e) =>
ClosingTab?.Invoke(this, e);
public event EventHandler<AddingTabEventArgs> AddingTab;
protected virtual void OnAddingTab(AddingTabEventArgs e) =>
AddingTab?.Invoke(this, e);
const int TCM_SETMINTABWIDTH = 0x1300 + 49;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
public class ClosingTabEventArgs : EventArgs
{
public ClosingTabEventArgs(TabPage tp) => TabPage = tp;
public TabPage TabPage { get; }
public bool Cancel { get; set; }
}
public class AddingTabEventArgs : EventArgs
{
public AddingTabEventArgs() { }
public bool Cancel { get; set; }
}
}
请注意,我又添加了两个事件,AddingTab
和 ClosingTab
以在您的实施中捕获它们并执行您需要的任何操作,包括取消。
private void tabControlEx1_AddingTab(object sender, AddingTabEventArgs e)
{
if (MessageBox.Show("Add new TabPage?", "Alert",
MessageBoxButtons.YesNo) == DialogResult.No)
e.Cancel = true;
}
private void tabControlEx1_ClosingTab(object sender, ClosingTabEventArgs e)
{
if (MessageBox.Show($"Remove {e.TabPage.Text}?", "Alert",
MessageBoxButtons.YesNo) == DialogResult.No)
e.Cancel = true;
}
当然,您可以进一步扩展控件并添加更多绘图属性,例如 back/foreground 普通选项卡和选定选项卡的颜色。另外,您可以尝试 LinearGradientBrush
填充背景而不是实心画笔。
重建,在ToolBox
window之上,找到并放下一个实例。尝试返回代码以添加您的风格。
我不太确定我哪里出错了,但在我将自定义背景色添加到我的 tabControl1 之前一切正常,我看到其他选项卡上的 X 和添加选项卡的 +
添加此代码源后,我添加的选项卡不存在了,但 + 按钮功能和其他选项卡功能也让我觉得 backColor 只是将它们隐藏在后面。
SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
e.Graphics.FillRectangle(backColor, rec);
有没有什么方法可以让标签页完全显示我用背景颜色放入的 DrawItem?
代码来源:
private void tabControl1_DrawItem_1(object sender, DrawItemEventArgs e)
{
Rectangle rec = tabControl1.ClientRectangle;
SolidBrush backColor = new SolidBrush(Color.FromArgb(40, 40, 40)); // change back color
e.Graphics.FillRectangle(backColor, rec);
StringFormat StrFormat = new StringFormat();
StrFormat.LineAlignment = StringAlignment.Center;
StrFormat.Alignment = StringAlignment.Center;
Brush bshBack = new SolidBrush(Color.FromArgb(55, 55, 55)); // change tab color
var tabPage = this.tabControl1.TabPages[e.Index];
var tabRect = this.tabControl1.GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
if (e.Index == this.tabControl1.TabCount - 1)
{
// Add
var addImage = Properties.Resources.Add;
e.Graphics.FillRectangle(bshBack, e.Bounds);
e.Graphics.DrawImage(addImage,
tabRect.Left + (tabRect.Width - addImage.Width) / 2,
tabRect.Top + (tabRect.Height - addImage.Height) / 2);
}
else
{
// Close
var closeImage = Properties.Resources.Close;
e.Graphics.FillRectangle(bshBack, e.Bounds);
e.Graphics.DrawImage(closeImage,
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font,
tabRect, tabPage.ForeColor, TextFormatFlags.Left);
}
}
扩展 TabControl
,在构造函数中设置如下所示的控件样式,主要是按照你想要的方式绘制控件和选项卡。
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
namespace YourProjectNamespace
{
[DesignerCategory("Code")]
[ToolboxBitmap(typeof(TabControl))]
public class TabControlEx : TabControl
{
public TabControlEx() : base()
{
SetStyle(ControlStyles.AllPaintingInWmPaint
| ControlStyles.ResizeRedraw
| ControlStyles.OptimizedDoubleBuffer
| ControlStyles.UserPaint, true);
UpdateStyles();
Padding = new Point(14, 4);
}
private Color backColor = Color.FromArgb(40, 40, 40);
/// <inheritdoc cref="Control.BackColor"/>
[DefaultValue(typeof(Color), "40, 40, 40"),
Browsable(true),
EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new Color BackColor
{
get => backColor;
set
{
if (backColor != value)
{
backColor = value;
Invalidate();
}
}
}
private Image addImage;
[DefaultValue(null)]
public Image AddButtonImage
{
get => addImage;
set
{
addImage = value;
Invalidate();
}
}
private Image closeImage;
[DefaultValue(null)]
public Image CloseButtonImage
{
get => closeImage;
set
{
closeImage = value;
Invalidate();
}
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
SendMessage(Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
if (TabCount > 0) TabPages[TabCount - 1].Text = "";
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.Clear(BackColor);
if (TabCount == 0) return;
for (int i = 0; i < TabCount; i++)
{
var tp = TabPages[i];
var r = Rectangle.Inflate(GetTabRect(i), -4, 0);
if (i == TabCount - 1)
{
if (AddButtonImage != null)
g.DrawImage(AddButtonImage,
r.X + (r.Width - AddButtonImage.Width) / 2,
r.Y + (r.Height - AddButtonImage.Height) / 2,
AddButtonImage.Width, AddButtonImage.Height);
}
else
{
if (i == SelectedIndex)
using (var brSel = new SolidBrush(Color.FromArgb(105, 105, 105)))
g.FillRectangle(brSel, Rectangle.Inflate(r, 4, 1));
if (ImageList != null && tp.ImageIndex >= 0)
ImageList.Draw(g,
r.X, r.Y + (r.Height - ImageList.ImageSize.Height) / 2,
tp.ImageIndex);
if (CloseButtonImage != null)
{
var closeRect = new Rectangle(new Point(
r.Right - CloseButtonImage.Width,
r.Y + (r.Height - CloseButtonImage.Height) / 2),
CloseButtonImage.Size);
g.DrawImage(CloseButtonImage, closeRect,
0, 0, CloseButtonImage.Width, CloseButtonImage.Height,
GraphicsUnit.Pixel);
}
TextRenderer.DrawText(g, tp.Text, tp.Font, r, Color.White,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter);
}
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
var lastIndex = TabCount - 1;
if (GetTabRect(lastIndex).Contains(e.Location))
{
var args = new AddingTabEventArgs();
OnAddingTab(args);
if (args.Cancel) return;
var newTp = new TabPage
{
Text = "New Tab",
BackColor = BackColor
};
TabPages.Insert(lastIndex, newTp);
SelectedIndex = lastIndex;
}
else
{
for (var i = 0; i < TabPages.Count; i++)
{
var r = Rectangle.Inflate(GetTabRect(i), -4, 0);
if (new Rectangle(r.Right - 16, r.Y + (r.Height - 16), 16, 16)
.Contains(e.Location))
{
var args = new ClosingTabEventArgs(TabPages[i]);
OnClosingTab(args);
if (args.Cancel) return;
TabPages[i].Dispose();
break;
}
}
}
}
protected override void OnSelecting(TabControlCancelEventArgs e)
{
if (e.TabPageIndex == TabCount - 1)
e.Cancel = true;
else
base.OnSelecting(e);
}
public event EventHandler<ClosingTabEventArgs> ClosingTab;
protected virtual void OnClosingTab(ClosingTabEventArgs e) =>
ClosingTab?.Invoke(this, e);
public event EventHandler<AddingTabEventArgs> AddingTab;
protected virtual void OnAddingTab(AddingTabEventArgs e) =>
AddingTab?.Invoke(this, e);
const int TCM_SETMINTABWIDTH = 0x1300 + 49;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
public class ClosingTabEventArgs : EventArgs
{
public ClosingTabEventArgs(TabPage tp) => TabPage = tp;
public TabPage TabPage { get; }
public bool Cancel { get; set; }
}
public class AddingTabEventArgs : EventArgs
{
public AddingTabEventArgs() { }
public bool Cancel { get; set; }
}
}
请注意,我又添加了两个事件,AddingTab
和 ClosingTab
以在您的实施中捕获它们并执行您需要的任何操作,包括取消。
private void tabControlEx1_AddingTab(object sender, AddingTabEventArgs e)
{
if (MessageBox.Show("Add new TabPage?", "Alert",
MessageBoxButtons.YesNo) == DialogResult.No)
e.Cancel = true;
}
private void tabControlEx1_ClosingTab(object sender, ClosingTabEventArgs e)
{
if (MessageBox.Show($"Remove {e.TabPage.Text}?", "Alert",
MessageBoxButtons.YesNo) == DialogResult.No)
e.Cancel = true;
}
当然,您可以进一步扩展控件并添加更多绘图属性,例如 back/foreground 普通选项卡和选定选项卡的颜色。另外,您可以尝试 LinearGradientBrush
填充背景而不是实心画笔。
重建,在ToolBox
window之上,找到并放下一个实例。尝试返回代码以添加您的风格。