官网
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
目录
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 }
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 }
用处及效果
用处:你可以把它当作一个panel来用,比如需要包裹一些控件并显示一个圆角边框的时候,你应该想到用这个控件
效果图:其实就是一个圆角边框的面板
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧