winfrom 自定义tab 标签



using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using System.ComponentModel;
 
namespace GAXT.RIS.RIS.Control.FrmBci.Control
{
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(TabControl))]
    public partial class UcCustomTabControl : TabControl
    {
        #region 常量与字段
        private readonly Color _targetColor = Color.FromArgb(25, 25, 111);
        private const int TEXT_PADDING = 20;
        private const int MIN_TAB_WIDTH = 100;
        private const int SELECTED_TAB_BORDER_WIDTH = 2;
        private const int UNSELECTED_TAB_BORDER_WIDTH = 1;
 
        private Rectangle[] _tabRects;
        private string[] _cachedTabTexts;
        private bool _isCalculatingRects;
        private StringFormat _stringFormat;
        private Pen _selectedBorderPen;
        private Pen _unselectedBorderPen;
        private Pen _separatorPen;
        private SolidBrush _targetBrush;
        private SolidBrush _selectedTabBrush;
        private SolidBrush _selectedTextBrush;
        private SolidBrush _unselectedTextBrush;
        private SolidBrush _textShadowBrush;
        #endregion
 
        #region 属性
        [Category("外观")]
        [Description("选中标签的背景色")]
        public Color SelectedTabColor { get; set; } = Color.FromArgb(135, 206, 250);
 
        [Category("外观")]
        [Description("选中标签的文字颜色")]
        public Color SelectedTextColor { get; set; } = Color.Yellow;
 
        [Category("外观")]
        [Description("未选中标签的文字颜色")]
        public Color UnselectedTextColor { get; set; } = Color.White;
 
        [Category("外观")]
        [Description("文字阴影颜色")]
        public Color TextShadowColor { get; set; } = Color.Black;
 
        [Category("外观")]
        [Description("未选中标签的字体大小")]
        public float UnselectedTabFontSize { get; set; } = 12F;
 
        [Category("行为")]
        [Description("是否显示标签分隔线")]
        public bool ShowSeparators { get; set; } = true;
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabDrawMode DrawMode
        {
            get => base.DrawMode;
            private set => base.DrawMode = value;
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabAlignment Alignment
        {
            get => base.Alignment;
            private set => base.Alignment = value;
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabSizeMode SizeMode
        {
            get => base.SizeMode;
            private set => base.SizeMode = value;
        }
        #endregion
 
        #region 构造函数
        public UcCustomTabControl()
        {
            InitializeComponent();
            InitializeControl();
            InitializeResources();
        }
 
        
 
        private void InitializeControl()
        {
            SetStyle(ControlStyles.UserPaint |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.SupportsTransparentBackColor, true);
 
            DrawMode = TabDrawMode.OwnerDrawFixed;
            Alignment = TabAlignment.Top;
            SizeMode = TabSizeMode.Normal;
 
            Font = new Font("微软雅黑", 8F, FontStyle.Bold, GraphicsUnit.Point, 134);
            ItemSize = new Size(150, 45);
            Padding = new Point(10, 5);
        }
 
        private void InitializeResources()
        {
            _stringFormat = new StringFormat(StringFormat.GenericTypographic)
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center,
                Trimming = StringTrimming.EllipsisCharacter,
                FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoClip
            };
 
            _selectedBorderPen = new Pen(Color.White, SELECTED_TAB_BORDER_WIDTH);
            _unselectedBorderPen = new Pen(Color.White, UNSELECTED_TAB_BORDER_WIDTH);
            _separatorPen = new Pen(Color.White, 1);
 
            _targetBrush = new SolidBrush(_targetColor);
            _selectedTabBrush = new SolidBrush(SelectedTabColor);
            _selectedTextBrush = new SolidBrush(SelectedTextColor);
            _unselectedTextBrush = new SolidBrush(UnselectedTextColor);
            _textShadowBrush = new SolidBrush(TextShadowColor);
        }
        #endregion
 
        #region 核心方法
        private void CalculateTabRects(Graphics g = null)
        {
            if (_isCalculatingRects) return;
 
            _isCalculatingRects = true;
            bool createdGraphics = false;
 
            try
            {
                if (g == null)
                {
                    g = CreateGraphics();
                    createdGraphics = true;
                }
 
                if (TabCount == 0)
                {
                    _tabRects = Array.Empty<Rectangle>();
                    _cachedTabTexts = Array.Empty<string>();
                    return;
                }
 
                var newRects = new Rectangle[TabCount];
                var newTexts = new string[TabCount];
 
                int currentX = 0;
                int tabHeight = ItemSize.Height;
                int tabY = 0;
 
                for (int i = 0; i < TabCount; i++)
                {
                    string tabText = TabPages[i].Text;
                    newTexts[i] = tabText;
 
                    int tabWidth = CalculateTabWidth(i, tabText, g);
                    newRects[i] = new Rectangle(currentX, tabY, tabWidth, tabHeight);
                    currentX += tabWidth;
                }
 
                _tabRects = newRects;
                _cachedTabTexts = newTexts;
            }
            finally
            {
                _isCalculatingRects = false;
                if (createdGraphics)
                    g?.Dispose();
            }
        }
 
        private int CalculateTabWidth(int tabIndex, string tabText, Graphics g)
        {
            if (string.IsNullOrEmpty(tabText)) return MIN_TAB_WIDTH;
 
            Font measurementFont = GetTabFont(tabIndex);
            bool shouldDisposeFont = measurementFont != Font;
 
            try
            {
                SizeF textSize = g.MeasureString(tabText, measurementFont,
                    new SizeF(int.MaxValue, ItemSize.Height), _stringFormat);
 
                int calculatedWidth = (int)Math.Ceiling(textSize.Width) + TEXT_PADDING;
                return Math.Max(calculatedWidth, MIN_TAB_WIDTH);
            }
            finally
            {
                if (shouldDisposeFont)
                    measurementFont.Dispose();
            }
        }
 
        private Font GetTabFont(int tabIndex)
        {
            return tabIndex == SelectedIndex ?
                Font :
                new Font(Font.FontFamily, UnselectedTabFontSize, FontStyle.Bold);
        }
 
        protected new Rectangle GetTabRect(int index)
        {
            if (index < 0 || index >= TabCount)
                return Rectangle.Empty;
 
            if (_tabRects == null || _tabRects.Length != TabCount || HasTabTextChanged())
                CalculateTabRects();
 
            return _tabRects != null && index < _tabRects.Length ?
                _tabRects[index] :
                base.GetTabRect(index);
        }
 
        private bool HasTabTextChanged()
        {
            if (_cachedTabTexts == null || _cachedTabTexts.Length != TabCount)
                return true;
 
            for (int i = 0; i < TabCount; i++)
            {
                if (_cachedTabTexts[i] != TabPages[i].Text)
                    return true;
            }
 
            return false;
        }
        #endregion
 
        #region 绘制方法
        protected override void OnPaint(PaintEventArgs e)
        {
            if (TabCount == 0) return;
 
            Graphics g = e.Graphics;
            SetupGraphics(g);
 
            // 绘制背景
            g.FillRectangle(_targetBrush, ClientRectangle);
 
            // 确保标签区域已计算
            if (_tabRects == null || _tabRects.Length != TabCount || HasTabTextChanged())
                CalculateTabRects(g);
 
            // 绘制所有标签
            for (int i = 0; i < TabCount; i++)
            {
                Rectangle tabBounds = GetTabRect(i);
                if (tabBounds.IsEmpty) continue;
 
                DrawItemEventArgs args = new DrawItemEventArgs(
                    g, Font, tabBounds, i,
                    i == SelectedIndex ? DrawItemState.Selected : DrawItemState.Default,
                    ForeColor, BackColor);
 
                OnDrawItem(args);
            }
 
            UpdateSelectedPageBounds();
        }
 
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index < 0 || e.Index >= TabCount) return;
 
            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 
            Rectangle tabRect = e.Bounds;
            string tabText = TabPages[e.Index].Text;
 
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                DrawSelectedTab(e.Graphics, tabRect, tabText);
            else
                DrawUnselectedTab(e.Graphics, tabRect, tabText);
 
            // 绘制分隔线
            if (ShowSeparators && e.Index < TabCount - 1)
                DrawSeparator(e.Graphics, tabRect);
        }
 
        private void DrawSelectedTab(Graphics g, Rectangle tabRect, string tabText)
        {
            g.FillRectangle(_selectedTabBrush, tabRect);
            g.DrawRectangle(_selectedBorderPen, tabRect);
            DrawTabText(g, tabRect, tabText, Font, _selectedTextBrush, true);
        }
 
        private void DrawUnselectedTab(Graphics g, Rectangle tabRect, string tabText)
        {
            g.FillRectangle(_targetBrush, tabRect);
            g.DrawRectangle(_unselectedBorderPen, tabRect);
 
            using (Font largeFont = new Font(Font.FontFamily, UnselectedTabFontSize, FontStyle.Bold))
            {
                DrawTabText(g, tabRect, tabText, largeFont, _unselectedTextBrush, true);
            }
        }
 
        private void DrawTabText(Graphics g, Rectangle tabRect, string text, Font font, Brush textBrush, bool withShadow)
        {
            if (withShadow)
            {
                Rectangle shadowRect = new Rectangle(tabRect.X + 1, tabRect.Y + 1, tabRect.Width, tabRect.Height);
                g.DrawString(text, font, _textShadowBrush, shadowRect, _stringFormat);
            }
 
            g.DrawString(text, font, textBrush, tabRect, _stringFormat);
        }
 
        private void DrawSeparator(Graphics g, Rectangle tabRect)
        {
            g.DrawLine(_separatorPen,
                tabRect.Right - 1, tabRect.Top + 5,
                tabRect.Right - 1, tabRect.Bottom - 5);
        }
 
        private void SetupGraphics(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        }
        #endregion
 
        #region 事件处理
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            InvalidateTabRects();
            Refresh();
        }
 
        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            InvalidateTabRects();
            Refresh();
        }
 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
 
            for (int i = 0; i < TabCount; i++)
            {
                Rectangle tabRect = GetTabRect(i);
                if (tabRect.Contains(e.Location))
                {
                    SelectedIndex = i;
                    break;
                }
            }
        }
 
        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            InvalidateTabRects();
        }
 
        protected override void OnControlRemoved(ControlEventArgs e)
        {
            base.OnControlRemoved(e);
            InvalidateTabRects();
        }
 
        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            InvalidateTabRects();
        }
 
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            InvalidateTabRects();
        }
 
        private void InvalidateTabRects()
        {
            _tabRects = null;
            _cachedTabTexts = null;
        }
 
        private void UpdateSelectedPageBounds()
        {
            if (SelectedIndex >= 0 && SelectedIndex < TabPages.Count && TabPages[SelectedIndex] != null)
            {
                TabPage selectedPage = TabPages[SelectedIndex];
                selectedPage.Location = new Point(0, ItemSize.Height);
                selectedPage.Size = new Size(ClientSize.Width, Math.Max(0, ClientSize.Height - ItemSize.Height));
            }
        }
        #endregion
 
        #region 清理资源
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // 释放托管资源
                _stringFormat?.Dispose();
                _selectedBorderPen?.Dispose();
                _unselectedBorderPen?.Dispose();
                _separatorPen?.Dispose();
                _targetBrush?.Dispose();
                _selectedTabBrush?.Dispose();
                _selectedTextBrush?.Dispose();
                _unselectedTextBrush?.Dispose();
                _textShadowBrush?.Dispose();
 
                _tabRects = null;
                _cachedTabTexts = null;
            }
            base.Dispose(disposing);
        }
        #endregion
 
        #region 设计时支持
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            InvalidateTabRects();
        }
 
        public override void Refresh()
        {
            InvalidateTabRects();
            base.Refresh();
        }
        #endregion
    }
}

第二版本



using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using System.ComponentModel;
 
namespace GAXT.RIS.RIS.Control.FrmBci.Control
{
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(TabControl))]
    public partial class UcCustomTabControl : TabControl
    {
        #region 常量与字段
        private readonly Color _targetColor = Color.FromArgb(25, 25, 111);
        private const int TEXT_PADDING = 20;
        private const int MIN_TAB_WIDTH = 100;
        private const int SELECTED_TAB_BORDER_WIDTH = 2;
        private const int UNSELECTED_TAB_BORDER_WIDTH = 1;
 
        private Rectangle[] _tabRects;
        private string[] _cachedTabTexts;
        private bool _isCalculatingRects;
        private StringFormat _stringFormat;
        private Pen _selectedBorderPen;
        private Pen _unselectedBorderPen;
        private Pen _separatorPen;
        private SolidBrush _targetBrush;
        private SolidBrush _selectedTabBrush;
        private SolidBrush _selectedTextBrush;
        private SolidBrush _unselectedTextBrush;
        private SolidBrush _textShadowBrush;
        #endregion
 
        #region 属性
        [Category("外观")]
        [Description("选中标签的背景色")]
        public Color SelectedTabColor { get; set; } = Color.FromArgb(135, 206, 250);
 
        [Category("外观")]
        [Description("选中标签的文字颜色")]
        public Color SelectedTextColor { get; set; } = Color.Yellow;
 
        [Category("外观")]
        [Description("未选中标签的文字颜色")]
        public Color UnselectedTextColor { get; set; } = Color.White;
 
        [Category("外观")]
        [Description("文字阴影颜色")]
        public Color TextShadowColor { get; set; } = Color.Black;
 
        [Category("外观")]
        [Description("未选中标签的字体大小")]
        public float UnselectedTabFontSize { get; set; } = 12F;
 
        [Category("行为")]
        [Description("是否显示标签分隔线")]
        public bool ShowSeparators { get; set; } = true;
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabDrawMode DrawMode
        {
            get => base.DrawMode;
            private set => base.DrawMode = value;
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabAlignment Alignment
        {
            get => base.Alignment;
            private set => base.Alignment = value;
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabSizeMode SizeMode
        {
            get => base.SizeMode;
            private set => base.SizeMode = value;
        }
        #endregion
 
        #region 构造函数
        public UcCustomTabControl()
        {
            InitializeComponent();
            InitializeControl();
            InitializeResources();
        }
 
 
 
        private void InitializeControl()
        {
            SetStyle(ControlStyles.UserPaint |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.SupportsTransparentBackColor, true);
 
            DrawMode = TabDrawMode.OwnerDrawFixed;
            Alignment = TabAlignment.Top;
            SizeMode = TabSizeMode.Normal;
 
            Font = new Font("微软雅黑", 8F, FontStyle.Bold, GraphicsUnit.Point, 134);
            ItemSize = new Size(150, 45);
            Padding = new Point(10, 5);
        }
 
        private void InitializeResources()
        {
            _stringFormat = new StringFormat(StringFormat.GenericTypographic)
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center,
                Trimming = StringTrimming.EllipsisCharacter,
                FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoClip
            };
 
            _selectedBorderPen = new Pen(Color.White, SELECTED_TAB_BORDER_WIDTH);
            _unselectedBorderPen = new Pen(Color.White, UNSELECTED_TAB_BORDER_WIDTH);
            _separatorPen = new Pen(Color.White, 1);
 
            _targetBrush = new SolidBrush(_targetColor);
            _selectedTabBrush = new SolidBrush(SelectedTabColor);
            _selectedTextBrush = new SolidBrush(SelectedTextColor);
            _unselectedTextBrush = new SolidBrush(UnselectedTextColor);
            _textShadowBrush = new SolidBrush(TextShadowColor);
        }
        #endregion
 
        #region 核心方法
        private void CalculateTabRects(Graphics g = null)
        {
            if (_isCalculatingRects) return;
 
            _isCalculatingRects = true;
            bool createdGraphics = false;
 
            try
            {
                if (g == null)
                {
                    g = CreateGraphics();
                    createdGraphics = true;
                }
 
                if (TabCount == 0)
                {
                    _tabRects = Array.Empty<Rectangle>();
                    _cachedTabTexts = Array.Empty<string>();
                    return;
                }
 
                var newRects = new Rectangle[TabCount];
                var newTexts = new string[TabCount];
 
                // 重置计算逻辑,使用系统ItemSize作为基础
                int currentX = 0;
                int tabHeight = ItemSize.Height;
                int tabY = 0;
 
                // 直接使用系统计算的矩形区域,确保准确性
                for (int i = 0; i < TabCount; i++)
                {
                    // 使用系统计算的矩形作为基础
                    Rectangle systemRect = base.GetTabRect(i);
                    string tabText = TabPages[i].Text;
                    newTexts[i] = tabText;
                    
                    // 直接使用系统矩形,确保与实际显示位置一致
                    newRects[i] = systemRect;
                }
 
                _tabRects = newRects;
                _cachedTabTexts = newTexts;
            }
            finally
            {
                _isCalculatingRects = false;
                if (createdGraphics)
                    g?.Dispose();
            }
        }
 
        private int CalculateTabWidth(int tabIndex, string tabText, Graphics g)
        {
            if (string.IsNullOrEmpty(tabText)) return MIN_TAB_WIDTH;
 
            Font measurementFont = GetTabFont(tabIndex);
            bool shouldDisposeFont = measurementFont != Font;
 
            try
            {
                SizeF textSize = g.MeasureString(tabText, measurementFont,
                    new SizeF(int.MaxValue, ItemSize.Height), _stringFormat);
 
                int calculatedWidth = (int)Math.Ceiling(textSize.Width) + TEXT_PADDING;
                return Math.Max(calculatedWidth, MIN_TAB_WIDTH);
            }
            finally
            {
                if (shouldDisposeFont)
                    measurementFont.Dispose();
            }
        }
 
        private Font GetTabFont(int tabIndex)
        {
            return tabIndex == SelectedIndex ?
                Font :
                new Font(Font.FontFamily, UnselectedTabFontSize, FontStyle.Bold);
        }
 
        protected new Rectangle GetTabRect(int index)
        {
            if (index < 0 || index >= TabCount)
                return Rectangle.Empty;
 
            if (_tabRects == null || _tabRects.Length != TabCount || HasTabTextChanged())
                CalculateTabRects();
 
            return _tabRects != null && index < _tabRects.Length ?
                _tabRects[index] :
                base.GetTabRect(index);
        }
 
        private bool HasTabTextChanged()
        {
            if (_cachedTabTexts == null || _cachedTabTexts.Length != TabCount)
                return true;
 
            for (int i = 0; i < TabCount; i++)
            {
                if (_cachedTabTexts[i] != TabPages[i].Text)
                    return true;
            }
 
            return false;
        }
        #endregion
 
        #region 绘制方法
        protected override void OnPaint(PaintEventArgs e)
        {
            if (TabCount == 0) return;
 
            Graphics g = e.Graphics;
            SetupGraphics(g);
 
            // 绘制背景
            g.FillRectangle(_targetBrush, ClientRectangle);
 
            // 确保标签区域已计算
            if (_tabRects == null || _tabRects.Length != TabCount || HasTabTextChanged())
                CalculateTabRects(g);
 
            // 绘制所有标签
            for (int i = 0; i < TabCount; i++)
            {
                Rectangle tabBounds = GetTabRect(i);
                if (tabBounds.IsEmpty) continue;
 
                DrawItemEventArgs args = new DrawItemEventArgs(
                    g, Font, tabBounds, i,
                    i == SelectedIndex ? DrawItemState.Selected : DrawItemState.Default,
                    ForeColor, BackColor);
 
                OnDrawItem(args);
            }
 
            UpdateSelectedPageBounds();
        }
 
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index < 0 || e.Index >= TabCount) return;
 
            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 
            Rectangle tabRect = e.Bounds;
            string tabText = TabPages[e.Index].Text;
 
            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                DrawSelectedTab(e.Graphics, tabRect, tabText);
            else
                DrawUnselectedTab(e.Graphics, tabRect, tabText);
 
            // 绘制分隔线
            if (ShowSeparators && e.Index < TabCount - 1)
                DrawSeparator(e.Graphics, tabRect);
        }
 
        private void DrawSelectedTab(Graphics g, Rectangle tabRect, string tabText)
        {
            g.FillRectangle(_selectedTabBrush, tabRect);
            g.DrawRectangle(_selectedBorderPen, tabRect);
            DrawTabText(g, tabRect, tabText, Font, _selectedTextBrush, true);
        }
 
        private void DrawUnselectedTab(Graphics g, Rectangle tabRect, string tabText)
        {
            g.FillRectangle(_targetBrush, tabRect);
            g.DrawRectangle(_unselectedBorderPen, tabRect);
 
            using (Font largeFont = new Font(Font.FontFamily, UnselectedTabFontSize, FontStyle.Bold))
            {
                DrawTabText(g, tabRect, tabText, largeFont, _unselectedTextBrush, true);
            }
        }
 
        private void DrawTabText(Graphics g, Rectangle tabRect, string text, Font font, Brush textBrush, bool withShadow)
        {
            if (withShadow)
            {
                Rectangle shadowRect = new Rectangle(tabRect.X + 1, tabRect.Y + 1, tabRect.Width, tabRect.Height);
                g.DrawString(text, font, _textShadowBrush, shadowRect, _stringFormat);
            }
 
            g.DrawString(text, font, textBrush, tabRect, _stringFormat);
        }
 
        private void DrawSeparator(Graphics g, Rectangle tabRect)
        {
            g.DrawLine(_separatorPen,
                tabRect.Right - 1, tabRect.Top + 5,
                tabRect.Right - 1, tabRect.Bottom - 5);
        }
 
        private void SetupGraphics(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        }
        #endregion
 
        #region 事件处理
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            InvalidateTabRects();
            Refresh();
        }
 
        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            InvalidateTabRects();
            Refresh();
        }
 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            // 恢复base.OnMouseDown(e),让系统处理点击检测
            base.OnMouseDown(e);
            
            // 刷新显示,确保自定义绘制正确
            Refresh();
        }
 
        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            InvalidateTabRects();
        }
 
        protected override void OnControlRemoved(ControlEventArgs e)
        {
            base.OnControlRemoved(e);
            InvalidateTabRects();
        }
 
        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            InvalidateTabRects();
        }
 
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            InvalidateTabRects();
        }
 
        private void InvalidateTabRects()
        {
            _tabRects = null;
            _cachedTabTexts = null;
        }
 
        private void UpdateSelectedPageBounds()
        {
            if (SelectedIndex >= 0 && SelectedIndex < TabPages.Count && TabPages[SelectedIndex] != null)
            {
                TabPage selectedPage = TabPages[SelectedIndex];
                selectedPage.Location = new Point(0, ItemSize.Height);
                selectedPage.Size = new Size(ClientSize.Width, Math.Max(0, ClientSize.Height - ItemSize.Height));
            }
        }
        #endregion
 
        #region 清理资源
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // 释放托管资源
                _stringFormat?.Dispose();
                _selectedBorderPen?.Dispose();
                _unselectedBorderPen?.Dispose();
                _separatorPen?.Dispose();
                _targetBrush?.Dispose();
                _selectedTabBrush?.Dispose();
                _selectedTextBrush?.Dispose();
                _unselectedTextBrush?.Dispose();
                _textShadowBrush?.Dispose();
 
                _tabRects = null;
                _cachedTabTexts = null;
            }
            base.Dispose(disposing);
        }
        #endregion
 
        #region 设计时支持
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            InvalidateTabRects();
        }
 
        public override void Refresh()
        {
            InvalidateTabRects();
            base.Refresh();
        }
        #endregion
    }
}

winfrom 自定义tab 标签

© 版权声明

相关文章

暂无评论

none
暂无评论...