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
相关产品推荐
相关产品推荐

