前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control>
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492  
<https://shang.qq.com/wpa/qunwpa?idkey=6e08741ef16fe53bf0314c1c9e336c4f626047943a8b76bac062361bab6b4f8d>
目录
https://www.cnblogs.com/bfyx/p/11364884.html 
<https://www.cnblogs.com/bfyx/p/11364884.html>
准备工作
自定义的分为控件和窗体2种类型,分别都有一个基类,基类实现公共的大部分工作
开始
首先从基类控件开始吧,
主要实现功能:
 * 圆角 
 * 边框 
 * 填充颜色 
添加一个用户控件,命名为UCControlBase,写入相关属性,包含圆角角度,边框颜色,边框宽度,填充颜色,背景色等
 1 private bool _isRadius = false;  2  3 private int _cornerRadius = 24;  4  5 
 6 private bool _isShowRect = false;  7  8 private Color _rectColor = 
Color.FromArgb(220, 220, 220);  9  10 private int _rectWidth = 1;  11  12 
private Color _fillColor = Color.Transparent;  13 /// <summary>  14 /// 是否圆角  15
/// </summary>  16 [Description("是否圆角"), Category("自定义")]  17 public bool 
IsRadius 18  {  19 get  20  {  21 return this._isRadius;  22  }  23 set  24  {  
25 this._isRadius = value;  26  }  27  }  28 //圆角角度  29 [Description("圆角角度"), 
Category("自定义")]  30 public int ConerRadius  31  {  32 get  33  {  34 return 
this._cornerRadius;  35  }  36 set  37  {  38 this._cornerRadius = value;  39  }
 40  }  41  42 /// <summary>  43 /// 是否显示边框  44 /// </summary>  45 [Description(
"是否显示边框"), Category("自定义")]  46 public bool IsShowRect  47  {  48 get  49  {  50
return this._isShowRect;  51  }  52 set  53  {  54 this._isShowRect = value;  55
 } 56  }  57 /// <summary>  58 /// 边框颜色  59 /// </summary>  60 [Description("
边框颜色"), Category("自定义")]  61 public Color RectColor  62  {  63 get  64  {  65 
return this._rectColor;  66  }  67 set  68  {  69 this._rectColor = value;  70 
this.Refresh();  71  }  72  }  73 /// <summary>  74 /// 边框宽度  75 /// </summary> 
 76 [Description("边框宽度"), Category("自定义")]  77 public int RectWidth  78  {  79 
get  80  {  81 return this._rectWidth;  82  }  83 set  84  {  85 this
._rectWidth = value;  86  }  87  }  88 /// <summary>  89 /// 
当使用边框时填充颜色,当值为背景色或透明色或空值则不填充 90 /// </summary>  91 [Description("
当使用边框时填充颜色,当值为背景色或透明色或空值则不填充"), Category("自定义")]  92 public Color FillColor  93 
 { 94 get  95  {  96 return this._fillColor;  97  }  98 set  99  { 100 this
._fillColor = value; 101  } 102 } 
需要做的就是重写OnPaint,来画边框以及填充颜色
 1 protected override void OnPaint(PaintEventArgs e)  2  {  3 if (this.Visible)
 4  {  5 if (this._isRadius)  6  {  7 this.SetWindowRegion();  8  }  9 if (this
._isShowRect)10  { 11 Color rectColor = this._rectColor; 12 Pen pen = new 
Pen(rectColor, (float)this._rectWidth); 13 Rectangle clientRectangle = base
.ClientRectangle;14 GraphicsPath graphicsPath = new GraphicsPath(); 15 
graphicsPath.AddArc(0, 0, _cornerRadius, _cornerRadius, 180f, 90f); 16 
graphicsPath.AddArc(clientRectangle.Width - _cornerRadius -1, 0, _cornerRadius, 
_cornerRadius, 270f, 90f);17 graphicsPath.AddArc(clientRectangle.Width - 
_cornerRadius -1, clientRectangle.Height - _cornerRadius - 1, _cornerRadius, 
_cornerRadius, 0f, 90f);18 graphicsPath.AddArc(0, clientRectangle.Height - 
_cornerRadius -1, _cornerRadius, _cornerRadius, 90f, 90f); 19  
graphicsPath.CloseFigure();20 e.Graphics.SmoothingMode = 
SmoothingMode.AntiAlias;21 if (_fillColor != Color.Empty && _fillColor != 
Color.Transparent && _fillColor !=this.BackColor) 22 e.Graphics.FillPath(new 
SolidBrush(this._fillColor), graphicsPath); 23  e.Graphics.DrawPath(pen, 
graphicsPath);24  } 25  } 26 base.OnPaint(e); 27  } 28 29 private void 
SetWindowRegion()30  { 31 GraphicsPath path = new GraphicsPath(); 32 Rectangle 
rect =new Rectangle(-1, -1, base.Width + 1, base.Height); 33 path = this
.GetRoundedRectPath(rect,this._cornerRadius); 34 base.Region = new Region(path);
35  } 36 37 private GraphicsPath GetRoundedRectPath(Rectangle rect, int radius) 
38  { 39 Rectangle rect2 = new Rectangle(rect.Location, new Size(radius, 
radius));40 GraphicsPath graphicsPath = new GraphicsPath(); 41 
graphicsPath.AddArc(rect2, 180f, 90f);//左上角 42 rect2.X = rect.Right - radius; 43
 graphicsPath.AddArc(rect2, 270f, 90f);//右上角 44 rect2.Y = rect.Bottom - radius; 
45 rect2.Width += 1; 46 rect2.Height += 1; 47 graphicsPath.AddArc(rect2, 360f, 
90f);//右下角 48 rect2.X = rect.Left; 49 graphicsPath.AddArc(rect2, 90f, 90f);//左下角
50  graphicsPath.CloseFigure(); 51 return graphicsPath; 52 } 
至此基类控件就完成了,下面是完成代码
 1 // 版权所有 黄正辉 交流群:568015492 QQ:623128629  2 // 文件名称:UCControlBase.cs  3 // 
创建日期:2019-08-15 16:04:12 4 // 功能描述:ControlBase  5 // 项目地址:
https://gitee.com/kwwwvagaa/net_winform_custom_control  6 using System;  7 using
 System.Collections.Generic; 8 using System.ComponentModel;  9 using 
System.Drawing; 10 using System.Data;  11 using System.Linq;  12 using 
System.Text; 13 using System.Windows.Forms;  14 using System.Drawing.Drawing2D; 
 15  16 namespace HZH_Controls.Controls  17 {  18 [Designer("
System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof
(System.ComponentModel.Design.IDesigner))] 19 public partial class 
UCControlBase : UserControl, IContainerControl 20  {  21 private bool _isRadius 
=false;  22  23 private int _cornerRadius = 24;  24  25  26 private bool 
_isShowRect =false;  27  28 private Color _rectColor = Color.FromArgb(220, 220, 
220);  29  30 private int _rectWidth = 1;  31  32 private Color _fillColor = 
Color.Transparent; 33 /// <summary>  34 /// 是否圆角  35 /// </summary>  36 
[Description("是否圆角"), Category("自定义")]  37 public bool IsRadius  38  {  39 get  
40  {  41 return this._isRadius;  42  }  43 set  44  {  45 this._isRadius = 
value; 46  }  47  }  48 //圆角角度  49 [Description("圆角角度"), Category("自定义")]  50 
public int ConerRadius  51  {  52 get  53  {  54 return this._cornerRadius;  55 
 } 56 set  57  {  58 this._cornerRadius = value;  59  }  60  }  61  62 /// 
<summary>  63 /// 是否显示边框  64 /// </summary>  65 [Description("是否显示边框"), 
Category("自定义")]  66 public bool IsShowRect  67  {  68 get  69  {  70 return 
this._isShowRect;  71  }  72 set  73  {  74 this._isShowRect = value;  75  }  76
 } 77 /// <summary>  78 /// 边框颜色  79 /// </summary>  80 [Description("边框颜色"), 
Category("自定义")]  81 public Color RectColor  82  {  83 get  84  {  85 return 
this._rectColor;  86  }  87 set  88  {  89 this._rectColor = value;  90 this
.Refresh(); 91  }  92  }  93 /// <summary>  94 /// 边框宽度  95 /// </summary>  96 
[Description("边框宽度"), Category("自定义")]  97 public int RectWidth  98  {  99 get 
100  { 101 return this._rectWidth; 102  } 103 set 104  { 105 this._rectWidth = 
value;106  } 107  } 108 /// <summary> 109 /// 当使用边框时填充颜色,当值为背景色或透明色或空值则不填充 110 
/// </summary> 111 [Description("当使用边框时填充颜色,当值为背景色或透明色或空值则不填充"), Category("自定义"
)]112 public Color FillColor 113  { 114 get 115  { 116 return this._fillColor; 
117  } 118 set 119  { 120 this._fillColor = value; 121  } 122  } 123 124 public 
UCControlBase()125  { 126 this.InitializeComponent(); 127 base
.SetStyle(ControlStyles.UserPaint,true); 128 base
.SetStyle(ControlStyles.AllPaintingInWmPaint,true); 129 base
.SetStyle(ControlStyles.DoubleBuffer,true); 130  } 131 132 protected override 
void OnPaint(PaintEventArgs e) 133  { 134 if (this.Visible) 135  { 136 if (this
._isRadius)137  { 138 this.SetWindowRegion(); 139  } 140 if (this._isShowRect) 
141  { 142 Color rectColor = this._rectColor; 143 Pen pen = new Pen(rectColor, (
float)this._rectWidth); 144 Rectangle clientRectangle = base.ClientRectangle; 
145 GraphicsPath graphicsPath = new GraphicsPath(); 146 graphicsPath.AddArc(0, 0
, _cornerRadius, _cornerRadius, 180f, 90f);147 
graphicsPath.AddArc(clientRectangle.Width - _cornerRadius -1, 0, _cornerRadius, 
_cornerRadius, 270f, 90f);148 graphicsPath.AddArc(clientRectangle.Width - 
_cornerRadius -1, clientRectangle.Height - _cornerRadius - 1, _cornerRadius, 
_cornerRadius, 0f, 90f);149 graphicsPath.AddArc(0, clientRectangle.Height - 
_cornerRadius -1, _cornerRadius, _cornerRadius, 90f, 90f); 150  
graphicsPath.CloseFigure();151 e.Graphics.SmoothingMode = 
SmoothingMode.AntiAlias;152 if (_fillColor != Color.Empty && _fillColor != 
Color.Transparent && _fillColor !=this.BackColor) 153 e.Graphics.FillPath(new 
SolidBrush(this._fillColor), graphicsPath); 154  e.Graphics.DrawPath(pen, 
graphicsPath);155  } 156  } 157 base.OnPaint(e); 158  } 159 160 private void 
SetWindowRegion()161  { 162 GraphicsPath path = new GraphicsPath(); 163 
Rectangle rect =new Rectangle(-1, -1, base.Width + 1, base.Height); 164 path = 
this.GetRoundedRectPath(rect, this._cornerRadius); 165 base.Region = new 
Region(path);166  } 167 168 private GraphicsPath GetRoundedRectPath(Rectangle 
rect,int radius) 169  { 170 Rectangle rect2 = new Rectangle(rect.Location, new 
Size(radius, radius));171 GraphicsPath graphicsPath = new GraphicsPath(); 172 
graphicsPath.AddArc(rect2, 180f, 90f);//左上角 173 rect2.X = rect.Right - radius; 
174 graphicsPath.AddArc(rect2, 270f, 90f);//右上角 175 rect2.Y = rect.Bottom - 
radius;176 rect2.Width += 1; 177 rect2.Height += 1; 178 
graphicsPath.AddArc(rect2, 360f, 90f);//右下角 179 rect2.X = rect.Left; 180 
graphicsPath.AddArc(rect2, 90f, 90f);//左下角 181  graphicsPath.CloseFigure(); 182 
return graphicsPath; 183  } 184 185 protected override void WndProc(ref Message 
m)186  { 187 if (m.Msg != 20) 188  { 189 base.WndProc(ref m); 190  } 191  } 192 
193 194  } 195 } View Code  1 partial class UCControlBase  2  {  3 /// <summary>
 4 /// 必需的设计器变量。  5 /// </summary>  6 private System.ComponentModel.IContainer 
components =null;  7  8 /// <summary>  9 /// 清理所有正在使用的资源。 10 /// </summary> 11 
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> 12 protected 
override void Dispose(bool disposing) 13  { 14 if (disposing && (components != 
null)) 15  { 16  components.Dispose(); 17  } 18 base.Dispose(disposing); 19  } 
20 21 #region 组件设计器生成的代码 22 23 /// <summary> 24 /// 设计器支持所需的方法 - 不要 25 /// 
使用代码编辑器修改此方法的内容。26 /// </summary> 27 private void InitializeComponent() 28  { 29
 components =new System.ComponentModel.Container(); 30 this.AutoScaleMode = 
System.Windows.Forms.AutoScaleMode.None;31 base.SuspendLayout(); 32 base
.AutoScaleDimensions =new SizeF(9f, 20f); 33 base.AutoScaleMode = 
System.Windows.Forms.AutoScaleMode.None;34 this.DoubleBuffered = true; 35 this
.Font =new Font("微软雅黑", 15f, FontStyle.Regular, GraphicsUnit.Pixel); 36 base
.Margin =new Padding(4, 5, 4, 5); 37 base.Name = "UCBase"; 38 base.Size = new 
Size(237, 154); 39 base.ResumeLayout(false); 40  } 41 42 #endregion 43 } View 
Code 
用处及效果
用处:你可以把它当作一个panel来用,比如需要包裹一些控件并显示一个圆角边框的时候,你应该想到用这个控件
效果图:其实就是一个圆角边框的面板
 
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control> 点个星星吧
热门工具 换一换