入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
https://www.cnblogs.com/bfyx/p/11364884.html
此控件在https://www.cnblogs.com/belx/articles/9188577.html基础上调整修改,特此感谢
添加一个用户组件,命名TabControlExt,继承自TabControl
几个重写属性
1 private Color _backColor = Color.White; 2 [Browsable(true)] 3 [EditorBrowsable(EditorBrowsableState.Always)] 4 [DefaultValue(typeof(Color), "White")] 5 public override Color BackColor 6 { 7 get { return _backColor; } 8 set 9 { 10 _backColor = value; 11 base.Invalidate(true); 12 } 13 } 14 15 private Color _borderColor = Color.FromArgb(232, 232, 232); 16 [DefaultValue(typeof(Color), "232, 232, 232")] 17 [Description("TabContorl边框色")] 18 public Color BorderColor 19 { 20 get { return _borderColor; } 21 set 22 { 23 _borderColor = value; 24 base.Invalidate(true); 25 } 26 } 27 28 private Color _headSelectedBackColor = Color.FromArgb(255, 85, 51); 29 [DefaultValue(typeof(Color), "255, 85, 51")] 30 [Description("TabPage头部选中后的背景颜色")] 31 public Color HeadSelectedBackColor 32 { 33 get { return _headSelectedBackColor; } 34 set { _headSelectedBackColor = value; } 35 } 36 37 private Color _headSelectedBorderColor = Color.FromArgb(232, 232, 232); 38 [DefaultValue(typeof(Color), "232, 232, 232")] 39 [Description("TabPage头部选中后的边框颜色")] 40 public Color HeadSelectedBorderColor 41 { 42 get { return _headSelectedBorderColor; } 43 set { _headSelectedBorderColor = value; } 44 } 45 46 private Color _headerBackColor = Color.White; 47 [DefaultValue(typeof(Color), "White")] 48 [Description("TabPage头部默认背景颜色")] 49 public Color HeaderBackColor 50 { 51 get { return _headerBackColor; } 52 set { _headerBackColor = value; } 53 }
重写背景
1 protected override void OnPaintBackground(PaintEventArgs pevent) 2 { 3 if (this.DesignMode == true) 4 { 5 LinearGradientBrush backBrush = new LinearGradientBrush( 6 this.Bounds, 7 SystemColors.ControlLightLight, 8 SystemColors.ControlLight, 9 LinearGradientMode.Vertical); 10 pevent.Graphics.FillRectangle(backBrush, this.Bounds); 11 backBrush.Dispose(); 12 } 13 else 14 { 15 this.PaintTransparentBackground(pevent.Graphics, this.ClientRectangle); 16 } 17 } 18 ///19 /// TabContorl 背景色设置 20 /// 21 /// 22 /// 23 protected void PaintTransparentBackground(Graphics g, Rectangle clipRect) 24 { 25 if ((this.Parent != null)) 26 { 27 clipRect.Offset(this.Location); 28 PaintEventArgs e = new PaintEventArgs(g, clipRect); 29 GraphicsState state = g.Save(); 30 g.SmoothingMode = SmoothingMode.HighSpeed; 31 try 32 { 33 g.TranslateTransform((float)-this.Location.X, (float)-this.Location.Y); 34 this.InvokePaintBackground(this.Parent, e); 35 this.InvokePaint(this.Parent, e); 36 } 37 finally 38 { 39 g.Restore(state); 40 clipRect.Offset(-this.Location.X, -this.Location.Y); 41 //新加片段,待测试 42 using (SolidBrush brush = new SolidBrush(_backColor)) 43 { 44 clipRect.Inflate(1, 1); 45 g.FillRectangle(brush, clipRect); 46 } 47 } 48 } 49 else 50 { 51 System.Drawing.Drawing2D.LinearGradientBrush backBrush = new System.Drawing.Drawing2D.LinearGradientBrush(this.Bounds, SystemColors.ControlLightLight, SystemColors.ControlLight, System.Drawing.Drawing2D.LinearGradientMode.Vertical); 52 g.FillRectangle(backBrush, this.Bounds); 53 backBrush.Dispose(); 54 } 55 }
重绘
1 protected override void OnPaint(PaintEventArgs e) 2 { 3 // Paint the Background 4 base.OnPaint(e); 5 this.PaintTransparentBackground(e.Graphics, this.ClientRectangle); 6 this.PaintAllTheTabs(e); 7 this.PaintTheTabPageBorder(e); 8 this.PaintTheSelectedTab(e); 9 }
辅助函数
1 private void PaintAllTheTabs(System.Windows.Forms.PaintEventArgs e) 2 { 3 if (this.TabCount > 0) 4 { 5 for (int index = 0; index < this.TabCount; index++) 6 { 7 this.PaintTab(e, index); 8 } 9 } 10 } 11 12 private void PaintTab(System.Windows.Forms.PaintEventArgs e, int index) 13 { 14 GraphicsPath path = this.GetTabPath(index); 15 this.PaintTabBackground(e.Graphics, index, path); 16 this.PaintTabBorder(e.Graphics, index, path); 17 this.PaintTabText(e.Graphics, index); 18 this.PaintTabImage(e.Graphics, index); 19 } 20 21 ///22 /// 设置选项卡头部颜色 23 /// 24 /// 25 /// 26 /// 27 private void PaintTabBackground(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path) 28 { 29 Rectangle rect = this.GetTabRect(index); 30 System.Drawing.Brush buttonBrush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, _headerBackColor, _headerBackColor, LinearGradientMode.Vertical); //非选中时候的 TabPage 页头部背景色 31 graph.FillPath(buttonBrush, path); 32 //if (index == this.SelectedIndex) 33 //{ 34 // //buttonBrush = new System.Drawing.SolidBrush(_headSelectedBackColor); 35 // graph.DrawLine(new Pen(_headerBackColor), rect.Right+2, rect.Bottom, rect.Left + 1, rect.Bottom); 36 //} 37 buttonBrush.Dispose(); 38 } 39 40 ///41 /// 设置选项卡头部边框色 42 /// 43 /// 44 /// 45 /// 46 private void PaintTabBorder(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path) 47 { 48 Pen borderPen = new Pen(_borderColor);// TabPage 非选中时候的 TabPage 头部边框色 49 if (index == this.SelectedIndex) 50 { 51 borderPen = new Pen(_headSelectedBorderColor); // TabPage 选中后的 TabPage 头部边框色 52 } 53 graph.DrawPath(borderPen, path); 54 borderPen.Dispose(); 55 } 56 57 private void PaintTabImage(System.Drawing.Graphics g, int index) 58 { 59 Image tabImage = null; 60 if (this.TabPages[index].ImageIndex > -1 && this.ImageList != null) 61 { 62 tabImage = this.ImageList.Images[this.TabPages[index].ImageIndex]; 63 } 64 else if (this.TabPages[index].ImageKey.Trim().Length > 0 && this.ImageList != null) 65 { 66 tabImage = this.ImageList.Images[this.TabPages[index].ImageKey]; 67 } 68 if (tabImage != null) 69 { 70 Rectangle rect = this.GetTabRect(index); 71 g.DrawImage(tabImage, rect.Right - rect.Height - 4, 4, rect.Height - 2, rect.Height - 2); 72 } 73 } 74 75 private void PaintTabText(System.Drawing.Graphics graph, int index) 76 { 77 string tabtext = this.TabPages[index].Text; 78 79 System.Drawing.StringFormat format = new System.Drawing.StringFormat(); 80 format.Alignment = StringAlignment.Near; 81 format.LineAlignment = StringAlignment.Center; 82 format.Trimming = StringTrimming.EllipsisCharacter; 83 84 Brush forebrush = null; 85 86 if (this.TabPages[index].Enabled == false) 87 { 88 forebrush = SystemBrushes.ControlDark; 89 } 90 else 91 { 92 forebrush = SystemBrushes.ControlText; 93 } 94 95 Font tabFont = this.Font; 96 if (index == this.SelectedIndex) 97 { 98 if (this.TabPages[index].Enabled != false) 99 { 100 forebrush = new SolidBrush(_headSelectedBackColor); 101 } 102 } 103 104 Rectangle rect = this.GetTabRect(index); 105 106 var txtSize = ControlHelper.GetStringWidth(tabtext, graph, tabFont); 107 Rectangle rect2 = new Rectangle(rect.Left + (rect.Width - txtSize) / 2 - 1, rect.Top, rect.Width, rect.Height); 108 109 graph.DrawString(tabtext, tabFont, forebrush, rect2, format); 110 } 111 112 ///113 /// 设置 TabPage 内容页边框色 114 /// 115 /// 116 private void PaintTheTabPageBorder(System.Windows.Forms.PaintEventArgs e) 117 { 118 if (this.TabCount > 0) 119 { 120 Rectangle borderRect = this.TabPages[0].Bounds; 121 //borderRect.Inflate(1, 1); 122 Rectangle rect = new Rectangle(borderRect.X - 2, borderRect.Y-1, borderRect.Width + 5, borderRect.Height+2); 123 ControlPaint.DrawBorder(e.Graphics, rect, this.BorderColor, ButtonBorderStyle.Solid); 124 } 125 } 126 127 ///128 /// // TabPage 页头部间隔色 129 /// 130 /// 131 private void PaintTheSelectedTab(System.Windows.Forms.PaintEventArgs e) 132 { 133 if (this.SelectedIndex == -1) 134 return; 135 Rectangle selrect; 136 int selrectRight = 0; 137 selrect = this.GetTabRect(this.SelectedIndex); 138 selrectRight = selrect.Right; 139 e.Graphics.DrawLine(new Pen(_headSelectedBackColor), selrect.Left, selrect.Bottom + 1, selrectRight, selrect.Bottom + 1); 140 } 141 142 private GraphicsPath GetTabPath(int index) 143 { 144 System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); 145 path.Reset(); 146 147 Rectangle rect = this.GetTabRect(index); 148 149 switch (Alignment) 150 { 151 case TabAlignment.Top: 152 153 break; 154 case TabAlignment.Bottom: 155 156 break; 157 case TabAlignment.Left: 158 159 break; 160 case TabAlignment.Right: 161 162 break; 163 } 164 165 path.AddLine(rect.Left, rect.Top, rect.Left, rect.Bottom + 1); 166 path.AddLine(rect.Left, rect.Top, rect.Right , rect.Top); 167 path.AddLine(rect.Right , rect.Top, rect.Right , rect.Bottom + 1); 168 path.AddLine(rect.Right , rect.Bottom + 1, rect.Left, rect.Bottom + 1); 169 170 return path; 171 }
2个重写函数处理字体相关
1 [DllImport("user32.dll")] 2 private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 3 4 private const int WM_SETFONT = 0x30; 5 private const int WM_FONTCHANGE = 0x1d; 6 7 protected override void OnCreateControl() 8 { 9 base.OnCreateControl(); 10 this.OnFontChanged(EventArgs.Empty); 11 } 12 13 protected override void OnFontChanged(EventArgs e) 14 { 15 base.OnFontChanged(e); 16 IntPtr hFont = this.Font.ToHfont(); 17 SendMessage(this.Handle, WM_SETFONT, hFont, (IntPtr)(-1)); 18 SendMessage(this.Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero); 19 this.UpdateStyles(); 20 }
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace HZH_Controls.Controls
{
public class TabControlExt : TabControl
{
public TabControlExt()
: base()
{
SetStyles();
this.Multiline = true;
this.ItemSize = new Size(this.ItemSize.Width, 50);
}
private void SetStyles()
{
base.SetStyle(
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.SupportsTransparentBackColor, true);
base.UpdateStyles();
}
private Color _backColor = Color.White;
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DefaultValue(typeof(Color), "White")]
public override Color BackColor
{
get { return _backColor; }
set
{
_backColor = value;
base.Invalidate(true);
}
}
private Color _borderColor = Color.FromArgb(232, 232, 232);
[DefaultValue(typeof(Color), "232, 232, 232")]
[Description("TabContorl边框色")]
public Color BorderColor
{
get { return _borderColor; }
set
{
_borderColor = value;
base.Invalidate(true);
}
}
private Color _headSelectedBackColor = Color.FromArgb(255, 85, 51);
[DefaultValue(typeof(Color), "255, 85, 51")]
[Description("TabPage头部选中后的背景颜色")]
public Color HeadSelectedBackColor
{
get { return _headSelectedBackColor; }
set { _headSelectedBackColor = value; }
}
private Color _headSelectedBorderColor = Color.FromArgb(232, 232, 232);
[DefaultValue(typeof(Color), "232, 232, 232")]
[Description("TabPage头部选中后的边框颜色")]
public Color HeadSelectedBorderColor
{
get { return _headSelectedBorderColor; }
set { _headSelectedBorderColor = value; }
}
private Color _headerBackColor = Color.White;
[DefaultValue(typeof(Color), "White")]
[Description("TabPage头部默认背景颜色")]
public Color HeaderBackColor
{
get { return _headerBackColor; }
set { _headerBackColor = value; }
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
if (this.DesignMode == true)
{
LinearGradientBrush backBrush = new LinearGradientBrush(
this.Bounds,
SystemColors.ControlLightLight,
SystemColors.ControlLight,
LinearGradientMode.Vertical);
pevent.Graphics.FillRectangle(backBrush, this.Bounds);
backBrush.Dispose();
}
else
{
this.PaintTransparentBackground(pevent.Graphics, this.ClientRectangle);
}
}
///
/// TabContorl 背景色设置
///
///
///
protected void PaintTransparentBackground(Graphics g, Rectangle clipRect)
{
if ((this.Parent != null))
{
clipRect.Offset(this.Location);
PaintEventArgs e = new PaintEventArgs(g, clipRect);
GraphicsState state = g.Save();
g.SmoothingMode = SmoothingMode.HighSpeed;
try
{
g.TranslateTransform((float)-this.Location.X, (float)-this.Location.Y);
this.InvokePaintBackground(this.Parent, e);
this.InvokePaint(this.Parent, e);
}
finally
{
g.Restore(state);
clipRect.Offset(-this.Location.X, -this.Location.Y);
//新加片段,待测试
using (SolidBrush brush = new SolidBrush(_backColor))
{
clipRect.Inflate(1, 1);
g.FillRectangle(brush, clipRect);
}
}
}
else
{
System.Drawing.Drawing2D.LinearGradientBrush backBrush = new System.Drawing.Drawing2D.LinearGradientBrush(this.Bounds, SystemColors.ControlLightLight, SystemColors.ControlLight, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
g.FillRectangle(backBrush, this.Bounds);
backBrush.Dispose();
}
}
protected override void OnPaint(PaintEventArgs e)
{
// Paint the Background
base.OnPaint(e);
this.PaintTransparentBackground(e.Graphics, this.ClientRectangle);
this.PaintAllTheTabs(e);
this.PaintTheTabPageBorder(e);
this.PaintTheSelectedTab(e);
}
private void PaintAllTheTabs(System.Windows.Forms.PaintEventArgs e)
{
if (this.TabCount > 0)
{
for (int index = 0; index < this.TabCount; index++)
{
this.PaintTab(e, index);
}
}
}
private void PaintTab(System.Windows.Forms.PaintEventArgs e, int index)
{
GraphicsPath path = this.GetTabPath(index);
this.PaintTabBackground(e.Graphics, index, path);
this.PaintTabBorder(e.Graphics, index, path);
this.PaintTabText(e.Graphics, index);
this.PaintTabImage(e.Graphics, index);
}
///
/// 设置选项卡头部颜色
///
///
///
///
private void PaintTabBackground(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
{
Rectangle rect = this.GetTabRect(index);
System.Drawing.Brush buttonBrush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, _headerBackColor, _headerBackColor, LinearGradientMode.Vertical); //非选中时候的 TabPage 页头部背景色
graph.FillPath(buttonBrush, path);
//if (index == this.SelectedIndex)
//{
// //buttonBrush = new System.Drawing.SolidBrush(_headSelectedBackColor);
// graph.DrawLine(new Pen(_headerBackColor), rect.Right+2, rect.Bottom, rect.Left + 1, rect.Bottom);
//}
buttonBrush.Dispose();
}
///
/// 设置选项卡头部边框色
///
///
///
///
private void PaintTabBorder(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
{
Pen borderPen = new Pen(_borderColor);// TabPage 非选中时候的 TabPage 头部边框色
if (index == this.SelectedIndex)
{
borderPen = new Pen(_headSelectedBorderColor); // TabPage 选中后的 TabPage 头部边框色
}
graph.DrawPath(borderPen, path);
borderPen.Dispose();
}
private void PaintTabImage(System.Drawing.Graphics g, int index)
{
Image tabImage = null;
if (this.TabPages[index].ImageIndex > -1 && this.ImageList != null)
{
tabImage = this.ImageList.Images[this.TabPages[index].ImageIndex];
}
else if (this.TabPages[index].ImageKey.Trim().Length > 0 && this.ImageList != null)
{
tabImage = this.ImageList.Images[this.TabPages[index].ImageKey];
}
if (tabImage != null)
{
Rectangle rect = this.GetTabRect(index);
g.DrawImage(tabImage, rect.Right - rect.Height - 4, 4, rect.Height - 2, rect.Height - 2);
}
}
private void PaintTabText(System.Drawing.Graphics graph, int index)
{
string tabtext = this.TabPages[index].Text;
System.Drawing.StringFormat format = new System.Drawing.StringFormat();
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Center;
format.Trimming = StringTrimming.EllipsisCharacter;
Brush forebrush = null;
if (this.TabPages[index].Enabled == false)
{
forebrush = SystemBrushes.ControlDark;
}
else
{
forebrush = SystemBrushes.ControlText;
}
Font tabFont = this.Font;
if (index == this.SelectedIndex)
{
if (this.TabPages[index].Enabled != false)
{
forebrush = new SolidBrush(_headSelectedBackColor);
}
}
Rectangle rect = this.GetTabRect(index);
var txtSize = ControlHelper.GetStringWidth(tabtext, graph, tabFont);
Rectangle rect2 = new Rectangle(rect.Left + (rect.Width - txtSize) / 2 - 1, rect.Top, rect.Width, rect.Height);
graph.DrawString(tabtext, tabFont, forebrush, rect2, format);
}
///
/// 设置 TabPage 内容页边框色
///
///
private void PaintTheTabPageBorder(System.Windows.Forms.PaintEventArgs e)
{
if (this.TabCount > 0)
{
Rectangle borderRect = this.TabPages[0].Bounds;
//borderRect.Inflate(1, 1);
Rectangle rect = new Rectangle(borderRect.X - 2, borderRect.Y - 1, borderRect.Width + 5, borderRect.Height + 2);
ControlPaint.DrawBorder(e.Graphics, rect, this.BorderColor, ButtonBorderStyle.Solid);
}
}
///
/// // TabPage 页头部间隔色
///
///
private void PaintTheSelectedTab(System.Windows.Forms.PaintEventArgs e)
{
if (this.SelectedIndex == -1)
return;
Rectangle selrect;
int selrectRight = 0;
selrect = this.GetTabRect(this.SelectedIndex);
selrectRight = selrect.Right;
e.Graphics.DrawLine(new Pen(_headSelectedBackColor), selrect.Left, selrect.Bottom + 1, selrectRight, selrect.Bottom + 1);
}
private GraphicsPath GetTabPath(int index)
{
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
path.Reset();
Rectangle rect = this.GetTabRect(index);
switch (Alignment)
{
case TabAlignment.Top:
break;
case TabAlignment.Bottom:
break;
case TabAlignment.Left:
break;
case TabAlignment.Right:
break;
}
path.AddLine(rect.Left, rect.Top, rect.Left, rect.Bottom + 1);
path.AddLine(rect.Left, rect.Top, rect.Right, rect.Top);
path.AddLine(rect.Right, rect.Top, rect.Right, rect.Bottom + 1);
path.AddLine(rect.Right, rect.Bottom + 1, rect.Left, rect.Bottom + 1);
return path;
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private const int WM_SETFONT = 0x30;
private const int WM_FONTCHANGE = 0x1d;
protected override void OnCreateControl()
{
base.OnCreateControl();
this.OnFontChanged(EventArgs.Empty);
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
IntPtr hFont = this.Font.ToHfont();
SendMessage(this.Handle, WM_SETFONT, hFont, (IntPtr)(-1));
SendMessage(this.Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
this.UpdateStyles();
}
}
}
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星 星吧