You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# TabControl控件重设计:实现无边框、自定义选中与未选中配色

Winform 自定义TabControl样式实现解决方案

未完成需求实现思路

  • 实现未选中标签黑色背景、灰色文字
    你现有DrawItem逻辑本身已经处理了标签头的颜色规则,只需补充2项配置即可:1. 构造函数内设置Appearance = TabAppearance.FlatButtons去掉系统自带的标签凸起样式;2. 所有TabPage的BackColor设为黑色、TabControl本身的BackColor也设为黑色,避免页面区域颜色不匹配。
  • 去掉选中标签的虚线焦点框
    虚线框是控件默认的焦点提示效果,只需重写ShowFocusCues属性返回false,同时在WndProc中屏蔽焦点绘制消息,即可彻底隐藏虚线框。

现有代码优化点

  • 你当前代码里每次绘制创建的Font、Brush、StringFormat等GDI对象没有释放,会造成内存泄漏,需要用using语句包裹或者使用完手动调用Dispose释放资源。
  • 不需要渐变效果时可以直接用SolidBrush替代LinearGradientBrush,减少不必要的性能开销。
  • 标签文字的对齐可以通过StringFormat的内置属性设置,避免手动调整坐标出现偏移。

修改后完整代码

class CustomTabControl : TabControl
{
    public CustomTabControl(): base()
    {
        this.DrawMode = TabDrawMode.OwnerDrawFixed;
        this.Appearance = TabAppearance.FlatButtons;
        this.ItemSize = new Size(100, 30); // 可根据需求调整标签尺寸
        this.BackColor = Color.Black;
        // 开启双缓冲避免绘制闪烁
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        this.DrawItem += tabControl1_DrawItem;
    }

    private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
    {
        Brush backBrush;
        Brush foreBrush;            
        
        if (e.Index == this.SelectedIndex)
        {            
            backBrush = new SolidBrush(Color.FromArgb(64,64,64));
            foreBrush = Brushes.White;                
        }
        else
        {
            backBrush = new SolidBrush(Color.Black);
            foreBrush = Brushes.Gray;
        }                

        string tabName = this.TabPages[e.Index].Text;
        // 设置文字居中对齐
        StringFormat tabFormat = new StringFormat()
        {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Center
        };

        // 绘制标签背景
        e.Graphics.FillRectangle(backBrush, e.Bounds);
        // 绘制标签文字
        using (Font tabFont = new Font(e.Font, FontStyle.Bold))
        {
            e.Graphics.DrawString(tabName, tabFont, foreBrush, e.Bounds, tabFormat);
        }

        // 绘制标签右侧剩余区域为黑色
        if (e.Index == this.TabPages.Count - 1)
        {
            Rectangle lastTabRect = this.GetTabRect(this.TabPages.Count - 1);
            RectangleF fillRect = new RectangleF(lastTabRect.X + lastTabRect.Width, lastTabRect.Y - 2, 
                this.Width - (lastTabRect.X + lastTabRect.Width), lastTabRect.Height + 4);
            e.Graphics.FillRectangle(Brushes.Black, fillRect);
        }

        // 释放GDI资源
        backBrush.Dispose();
        tabFormat.Dispose();
    }
    
    protected override void WndProc(ref Message m)
    {
        // 调整控件区域去掉边框
        if (m.Msg == 0x0005) // WM_SIZE消息
        {
            int width = unchecked((short)m.LParam);
            int height = unchecked((short)((uint)m.LParam >> 16));
            Region = new Region(new Rectangle(4, 2, width - 8, height - 6));
        }
        base.WndProc(ref m);
    }

    // 禁用焦点提示,彻底去掉虚线框
    protected override bool ShowFocusCues => false;
}

使用说明

把控件添加到窗体后,将所有子TabPage的BackColor属性设置为黑色即可完全匹配目标效果。

内容的提问来源于stack exchange,提问作者A.bakker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:06:03