我需要一个具有不同 TabPage Header 的自定义 TabControl。我已将 DrawMode 属性设置为“OwnerDrawFixed”,以便调用 OnDrawItem 方法。
在 OnDrawItem 方法中,我这样做:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
var tabPage = TabPages[e.Index];
if (tabPage != null)
{
if (tabPage is BackOfficeTabPage)
{
((BackOfficeTabPage)tabPage).DrawTab(e.Graphics, GetTabRect(e.Index));
}
}
}
将为每个现有页面调用该代码,并带有匹配的索引。但无论我做什么,它总是使用相同的 Header。
他正在绘制的矩形似乎是正确的。我也试过这样:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
var tabPage = TabPages[e.Index];
if (tabPage != null)
{
if (tabPage is BackOfficeTabPage)
{
((BackOfficeTabPage)tabPage).DrawTab(e.Graphics, e.Bounds);
}
}
}
结果相同。那是我的 DrawTab 函数:
internal void DrawTab(Graphics g, Rectangle rect)
{
if (State != null)
{
if (State.HasInvalidBuffers())
{
CreateFrames(rect);
}
if (State.IsInvalidate)
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
if (State.IsHover)
{
g.DrawImage(State.HoverBufferFrame, rect);
}
else if (State.IsSelected)
{
g.DrawImage(State.SelectionBufferFrame, rect);
}
else
{
g.DrawImage(State.DefaultBufferFrame, rect);
}
if (State.IsCloseFocused)
{
g.DrawImage(State.FocusedCloseButtonBufferFrame, State.CloseButtonRectangle);
}
else
{
g.DrawImage(State.DefaultCloseButtonBufferFrame, State.CloseButtonRectangle);
}
State.IsInvalidate = false;
}
}
}
每个选项卡都应该是橙色的。但只有第一个会正确显示。(图片链接)
我不明白我的错误。
我希望有人能启发我:)
此致,
西蒙
*****更新***** 这是 TabPage 控件的完整代码,它正在执行选项卡绘制。我不确定为什么,但第二个选项卡中的缓冲区图像始终是透明的。
public sealed class BackOfficeTabPage : TabPage
{
#region Fields
private string _text = string.Empty;
private string _imageKey = string.Empty;
private TabState _tabstate = new TabState();
private Brush _regluarBrush = new SolidBrush(Color.Transparent);
private Brush _selectedBrush = null;
private Brush _hoverBrush = null;
private int _imageIndex = 0;
#endregion
#region Properties
public Brush RegularBrush
{
get
{
return _regluarBrush;
}
set
{
_regluarBrush = value;
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (ParentTabControl != null)
ParentTabControl.Invalidate();
}
}
public Brush SelectedBrush
{
get
{
return _selectedBrush;
}
set
{
_selectedBrush = value;
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (ParentTabControl != null)
ParentTabControl.Invalidate();
}
}
public Brush HoverBrush
{
get
{
return _hoverBrush;
}
set
{
_hoverBrush = value;
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (ParentTabControl != null)
ParentTabControl.Invalidate();
}
}
public BackOfficeTabControl ParentTabControl
{
get
{
if (Parent != null && Parent is BackOfficeTabControl)
return (BackOfficeTabControl)Parent;
return null;
}
}
public new int ImageIndex
{
get
{
return _imageIndex;
}
set
{
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (OnPropertyChanged != null)
OnPropertyChanged(this, new PropertyChangedEventArgs("ImageIndex", _imageIndex, value));
_imageIndex = value;
base.ImageIndex = value;
}
}
public new string ImageKey
{
get
{
return _imageKey;
}
set
{
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (OnPropertyChanged != null)
OnPropertyChanged(this, new PropertyChangedEventArgs("ImageKey", _imageKey, value));
_imageKey = value;
base.ImageKey = value;
}
}
public TabState State
{
get
{
return _tabstate;
}
set
{
if (OnPropertyChanged != null)
OnPropertyChanged(this, new PropertyChangedEventArgs("State", _tabstate, value));
_tabstate = value;
}
}
public new string Text
{
get { return _text; }
set
{
_tabstate.InvalidateImageBuffers();
_tabstate.IsInvalidate = true;
if (OnPropertyChanged != null)
OnPropertyChanged(this, new PropertyChangedEventArgs("Text", _text, value));
_text = value;
base.Text = value;
}
}
public Image AssocImage
{
get
{
Image image = null;
if ((!string.IsNullOrEmpty(ImageKey) || ImageIndex >= 0) && ParentTabControl.ImageList != null)
{
if (!string.IsNullOrEmpty(ImageKey))
image = ParentTabControl.ImageList.Images[ImageKey];
else
image = ParentTabControl.ImageList.Images[ImageIndex];
}
return null;
}
}
#endregion
#region Events
public event EventHandler<PropertyChangedEventArgs> OnPropertyChanged = null;
#endregion
#region Functions
internal void test(Rectangle rect)
{
if (State.HasInvalidBuffers())
{
CreateFrames(rect);
}
}
internal void DrawTab(Graphics g, Rectangle rect)
{
if (State != null)
{
if (State.HasInvalidBuffers())
{
CreateFrames(rect);
}
if (State.IsInvalidate)
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
if (State.IsHover)
{
g.DrawImage(State.HoverBufferFrame,rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
}
else if (State.IsSelected)
{
g.DrawImage(State.SelectionBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
}
else
{
g.DrawImage(State.DefaultBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
}
if (State.IsCloseFocused)
{
g.DrawImage(State.FocusedCloseButtonBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
}
else
{
g.DrawImage(State.DefaultCloseButtonBufferFrame, rect, rect.X, rect.Y, rect.Width, rect.Height, GraphicsUnit.Pixel);
}
State.IsInvalidate = false;
}
}
}
internal void CreateFrames(Rectangle rect)
{
Image image = AssocImage;
Rectangle imageRectangle = Rectangle.Empty, textRectangle = Rectangle.Empty, closeButtonRectangle = Rectangle.Empty;
if (image != null)
{
imageRectangle = new Rectangle(rect.X + 2, rect.Y + 2, ParentTabControl.ImageScaling.Width, ParentTabControl.ImageScaling.Height);
}
if (ParentTabControl != null && ParentTabControl.ShowCloseButton && ParentTabControl.CloseButtonImage != null)
{
closeButtonRectangle = new Rectangle(rect.X + rect.Width - (16), rect.Y + 2, 14, 14);
}
if (!string.IsNullOrEmpty(Text))
{
if (imageRectangle != Rectangle.Empty)
{
if (closeButtonRectangle != Rectangle.Empty)
{
textRectangle = new Rectangle(imageRectangle.X + imageRectangle.Width + 1, rect.Y, closeButtonRectangle.X - (imageRectangle.X + imageRectangle.Width + 2), rect.Height);
}
else
{
textRectangle = new Rectangle(imageRectangle.X + imageRectangle.Width + 1, rect.Y, rect.X + rect.Width - (imageRectangle.X + imageRectangle.Width + 2), rect.Height);
}
}
else
{
if (closeButtonRectangle != Rectangle.Empty)
{
textRectangle = new Rectangle(rect.X + 1, rect.Y, closeButtonRectangle.X - (rect.X + 2), rect.Height);
}
else
{
textRectangle = new Rectangle(rect.X + 1, rect.Y, rect.Width - 2, rect.Height);
}
}
}
State.ImageRectangle = rect;
State.CloseButtonRectangle = closeButtonRectangle;
CreateSelectionFrame(rect, imageRectangle, textRectangle);
CreateHoverFrame(rect, imageRectangle, textRectangle);
CreateDefaultFrame(rect, imageRectangle, textRectangle);
CreateCloseButtonFrames(closeButtonRectangle);
}
internal void CreateSelectionFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
{
if (rect != Rectangle.Empty)
{
Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(buffer))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Color light = SystemColors.Window, dark = Color.FromArgb(229, 195, 101);
g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
if (imageRect != Rectangle.Empty)
{
Image img = AssocImage;
if (img != null)
{
g.DrawImage(img, imageRect);
}
}
if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
{
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.EllipsisCharacter;
g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
}
}
State.SelectionBufferFrame = buffer;
}
}
internal void CreateHoverFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
{
if (rect != Rectangle.Empty)
{
Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(buffer))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Color light = Color.FromArgb(108, 116, 118), dark = Color.FromArgb(108, 116, 118);
g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
if (imageRect != Rectangle.Empty)
{
Image img = AssocImage;
if (img != null)
{
g.DrawImage(img, imageRect);
}
}
if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
{
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.EllipsisCharacter;
g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
}
}
State.HoverBufferFrame = buffer;
}
}
internal void CreateDefaultFrame(Rectangle rect, Rectangle imageRect, Rectangle textRect)
{
if (rect != Rectangle.Empty)
{
Image buffer = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(buffer))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Color light = Color.Orange, dark = Color.Orange;
g.FillRectangle(new LinearGradientBrush(rect, light, dark, LinearGradientMode.Vertical), rect);
if (imageRect != Rectangle.Empty)
{
Image img = AssocImage;
if (img != null)
{
g.DrawImage(img, imageRect);
}
}
if (!string.IsNullOrEmpty(Text) && textRect != Rectangle.Empty)
{
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.Trimming = StringTrimming.EllipsisCharacter;
g.DrawString(Text, this.Font, new SolidBrush(ForeColor), new RectangleF(textRect.X, textRect.Y, textRect.Width, textRect.Height), format);
}
}
State.DefaultBufferFrame = buffer;
}
}
internal void CreateCloseButtonFrames(Rectangle closeBtnRect)
{
if (closeBtnRect != Rectangle.Empty)
{
if (ParentTabControl != null && ParentTabControl.CloseButtonImage != null && ParentTabControl.ShowCloseButton)
{
//closeBtnRect
Image buffer = new Bitmap(closeBtnRect.Width, closeBtnRect.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(buffer))
{
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.FillRectangle(new SolidBrush(Color.Transparent), closeBtnRect);
g.DrawImage(SetImageOpacity(ParentTabControl.CloseButtonImage, 0.5f), closeBtnRect.X, closeBtnRect.Y, closeBtnRect.Width, closeBtnRect.Height);
}
State.DefaultCloseButtonBufferFrame = buffer;
buffer = new Bitmap(closeBtnRect.Width, closeBtnRect.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(buffer))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.FillRectangle(new SolidBrush(Color.Transparent), closeBtnRect);
g.DrawImage(ParentTabControl.CloseButtonImage, closeBtnRect.X, closeBtnRect.Y, closeBtnRect.Width, closeBtnRect.Height);
}
State.FocusedCloseButtonBufferFrame = buffer;
}
}
}
/// <summary>
/// method for changing the opacity of an image
/// </summary>
/// <param name="image">image to set opacity on</param>
/// <param name="opacity">percentage of opacity</param>
/// <returns></returns>
private Image SetImageOpacity(Image image, float opacity)
{
try
{
//create a Bitmap the size of the image provided
Bitmap bmp = new Bitmap(image.Width, image.Height);
//create a graphics object from the image
using (Graphics gfx = Graphics.FromImage(bmp))
{
//create a color matrix object
ColorMatrix matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = opacity;
//create image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color(opacity) of the image
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//now draw the image
gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
}
return bmp;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
#endregion
#region Constr
public BackOfficeTabPage() : base()
{
}
public BackOfficeTabPage(string text)
: base(text)
{
}
#endregion
}