官网
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
目录
https://www.cnblogs.com/bfyx/p/11364884.html
用处及效果
准备工作
依然gdi+和三角函数,不懂可以先百度下
一个控制转动方向的枚举
1 public enum ConveyorDirection 2 { 3 /// <summary> 4 /// The none 5 /// </summary> 6 None, 7 /// <summary> 8 /// The forward 9 /// </summary> 10 Forward, 11 /// <summary> 12 /// The backward 13 /// </summary> 14 Backward 15 }
一些控制属性
1 /// <summary> 2 /// The conveyor color 3 /// </summary> 4 private Color conveyorColor = Color.FromArgb(255, 77, 59); 5 6 /// <summary> 7 /// Gets or sets the color of the conveyor. 8 /// </summary> 9 /// <value>The color of the conveyor.</value> 10 [Description("传送带颜色"), Category("自定义")] 11 public Color ConveyorColor 12 { 13 get { return conveyorColor; } 14 set 15 { 16 conveyorColor = value; 17 Refresh(); 18 } 19 } 20 21 /// <summary> 22 /// The inclination 23 /// </summary> 24 private double inclination = 0; 25 26 /// <summary> 27 /// Gets or sets the inclination. 28 /// </summary> 29 /// <value>The inclination.</value> 30 [Description("传送带角度(-90<=value<=90)"), Category("自定义")] 31 public double Inclination 32 { 33 get { return inclination; } 34 set 35 { 36 if (value > 90 || value < -90) 37 return; 38 inclination = value; 39 ResetWorkingRect(); 40 Refresh(); 41 } 42 } 43 44 /// <summary> 45 /// The conveyor height 46 /// </summary> 47 private int conveyorHeight = 50; 48 49 /// <summary> 50 /// Gets or sets the height of the conveyor. 51 /// </summary> 52 /// <value>The height of the conveyor.</value> 53 [Description("传送带高度"), Category("自定义")] 54 public int ConveyorHeight 55 { 56 get { return conveyorHeight; } 57 set 58 { 59 conveyorHeight = value; 60 ResetWorkingRect(); 61 Refresh(); 62 } 63 } 64 65 /// <summary> 66 /// The conveyor direction 67 /// </summary> 68 private ConveyorDirection conveyorDirection = ConveyorDirection.Forward; 69 70 /// <summary> 71 /// Gets or sets the conveyor direction. 72 /// </summary> 73 /// <value>The conveyor direction.</value> 74 [Description("传送带运行方向"), Category("自定义")] 75 public ConveyorDirection ConveyorDirection 76 { 77 get { return conveyorDirection; } 78 set 79 { 80 conveyorDirection = value; 81 if (value == HZH_Controls.Controls.ConveyorDirection.None) 82 { 83 m_timer.Enabled = false; 84 Refresh(); 85 } 86 else 87 { 88 m_timer.Enabled = true; 89 } 90 } 91 } 92 93 /// <summary> 94 /// The liquid speed 95 /// </summary> 96 private int conveyorSpeed = 100; 97 98 /// <summary> 99 /// 传送带运行速度,越小,速度越快Gets or sets the ConveyorSpeed. 100 /// </summary> 101 /// <value>The liquid speed.</value> 102 [Description("传送带运行速度,越小,速度越快"), Category("自定义")] 103 public int ConveyorSpeed 104 { 105 get { return conveyorSpeed; } 106 set 107 { 108 if (value <= 0) 109 return; 110 conveyorSpeed = value; 111 m_timer.Interval = value; 112 } 113 } 114 115 /// <summary> 116 /// The m working rect 117 /// </summary> 118 Rectangle m_workingRect; 119 /// <summary> 120 /// The int line left 121 /// </summary> 122 int intLineLeft = 0; 123 /// <summary> 124 /// The m timer 125 /// </summary> 126 Timer m_timer;
大小和角度改变时重算画图区域
1 void UCConveyor_SizeChanged(object sender, EventArgs e) 2 { 3 ResetWorkingRect(); 4 } 5 6 /// <summary> 7 /// Resets the working rect. 8 /// </summary> 9 private void ResetWorkingRect() 10 { 11 if (inclination == 90 || inclination == -90) 12 { 13 m_workingRect = new Rectangle((this.Width - conveyorHeight) / 2, 1, conveyorHeight, this.Height - 2); 14 } 15 else if (inclination == 0) 16 { 17 m_workingRect = new Rectangle(1, (this.Height - conveyorHeight) / 2 + 1, this.Width - 2, conveyorHeight); 18 } 19 else 20 { 21 //根据角度计算需要的高度 22 int intHeight = (int)(Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000)) * (this.Width)); 23 if (intHeight >= this.Height) 24 intHeight = this.Height; 25 26 int intWidth = (int)(intHeight / (Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000)))); 27 intHeight += conveyorHeight; 28 if (intHeight >= this.Height) 29 intHeight = this.Height; 30 m_workingRect = new Rectangle((this.Width - intWidth) / 2 + 1, (this.Height - intHeight) / 2 + 1, intWidth - 2, intHeight - 2); 31 } 32 33 }
最重要的重绘
1 /// <summary> 2 /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。 3 /// </summary> 4 /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param> 5 protected override void OnPaint(PaintEventArgs e) 6 { 7 base.OnPaint(e); 8 var g = e.Graphics; 9 g.SetGDIHigh(); 10 //g.FillRectangle(new SolidBrush(Color.FromArgb(100, conveyorColor)), m_workingRect); 11 12 //轴 13 //左端 14 var rectLeft = new Rectangle(m_workingRect.Left + 5, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top) + 5, conveyorHeight - 10, conveyorHeight - 10); 15 g.FillEllipse(new SolidBrush(conveyorColor), rectLeft); 16 g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectLeft.Left + (rectLeft.Width - 6) / 2, rectLeft.Top + (rectLeft.Height - 6) / 2, 6, 6)); 17 //右端 18 var rectRight = new Rectangle(m_workingRect.Right - conveyorHeight + 5, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)) + 5, conveyorHeight - 10, conveyorHeight - 10); 19 g.FillEllipse(new SolidBrush(conveyorColor), rectRight); 20 g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectRight.Left + (rectRight.Width - 6) / 2, rectRight.Top + (rectRight.Height - 6) / 2, 6, 6)); 21 22 23 //传送带 24 //左端 25 GraphicsPath path = new GraphicsPath(); 26 path.AddArc(new Rectangle(m_workingRect.Left, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top), conveyorHeight, conveyorHeight), 90F - (float)inclination, 180F); 27 //右端 28 path.AddArc(new Rectangle(m_workingRect.Right - conveyorHeight, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)), conveyorHeight, conveyorHeight), 270 - (float)inclination, 180F); 29 path.CloseAllFigures(); 30 g.DrawPath(new Pen(new SolidBrush(conveyorColor), 3), path); 31 32 //液体流动 33 if (ConveyorDirection != ConveyorDirection.None) 34 { 35 Pen p = new Pen(new SolidBrush(Color.FromArgb(150, this.BackColor)), 4); 36 p.DashPattern = new float[] { 6, 6 }; 37 p.DashOffset = intLineLeft * (ConveyorDirection == ConveyorDirection.Forward ? -1 : 1); 38 g.DrawPath(p, path); 39 } 40 } 41 }
完整代码
1 // *********************************************************************** 2 // Assembly : HZH_Controls 3 // Created : 2019-09-05 4 // 5 // *********************************************************************** 6 // <copyright file="UCConveyor.cs"> 7 // Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com 8 // </copyright> 9 // 10 // Blog: https://www.cnblogs.com/bfyx 11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl 12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 13 // 14 // If you use this code, please keep this note. 15 // *********************************************************************** 16 using System; 17 using System.Collections.Generic; 18 using System.Linq; 19 using System.Text; 20 using System.Windows.Forms; 21 using System.Drawing; 22 using System.Drawing.Drawing2D; 23 using System.ComponentModel; 24 25 namespace HZH_Controls.Controls 26 { 27 /// <summary> 28 /// Class UCConveyor. 29 /// Implements the <see cref="System.Windows.Forms.UserControl" /> 30 /// </summary> 31 /// <seealso cref="System.Windows.Forms.UserControl" /> 32 public class UCConveyor : UserControl 33 { 34 /// <summary> 35 /// The conveyor color 36 /// </summary> 37 private Color conveyorColor = Color.FromArgb(255, 77, 59); 38 39 /// <summary> 40 /// Gets or sets the color of the conveyor. 41 /// </summary> 42 /// <value>The color of the conveyor.</value> 43 [Description("传送带颜色"), Category("自定义")] 44 public Color ConveyorColor 45 { 46 get { return conveyorColor; } 47 set 48 { 49 conveyorColor = value; 50 Refresh(); 51 } 52 } 53 54 /// <summary> 55 /// The inclination 56 /// </summary> 57 private double inclination = 0; 58 59 /// <summary> 60 /// Gets or sets the inclination. 61 /// </summary> 62 /// <value>The inclination.</value> 63 [Description("传送带角度(-90<=value<=90)"), Category("自定义")] 64 public double Inclination 65 { 66 get { return inclination; } 67 set 68 { 69 if (value > 90 || value < -90) 70 return; 71 inclination = value; 72 ResetWorkingRect(); 73 Refresh(); 74 } 75 } 76 77 /// <summary> 78 /// The conveyor height 79 /// </summary> 80 private int conveyorHeight = 50; 81 82 /// <summary> 83 /// Gets or sets the height of the conveyor. 84 /// </summary> 85 /// <value>The height of the conveyor.</value> 86 [Description("传送带高度"), Category("自定义")] 87 public int ConveyorHeight 88 { 89 get { return conveyorHeight; } 90 set 91 { 92 conveyorHeight = value; 93 ResetWorkingRect(); 94 Refresh(); 95 } 96 } 97 98 /// <summary> 99 /// The conveyor direction 100 /// </summary> 101 private ConveyorDirection conveyorDirection = ConveyorDirection.Forward; 102 103 /// <summary> 104 /// Gets or sets the conveyor direction. 105 /// </summary> 106 /// <value>The conveyor direction.</value> 107 [Description("传送带运行方向"), Category("自定义")] 108 public ConveyorDirection ConveyorDirection 109 { 110 get { return conveyorDirection; } 111 set 112 { 113 conveyorDirection = value; 114 if (value == HZH_Controls.Controls.ConveyorDirection.None) 115 { 116 m_timer.Enabled = false; 117 Refresh(); 118 } 119 else 120 { 121 m_timer.Enabled = true; 122 } 123 } 124 } 125 126 /// <summary> 127 /// The liquid speed 128 /// </summary> 129 private int conveyorSpeed = 100; 130 131 /// <summary> 132 /// 传送带运行速度,越小,速度越快Gets or sets the ConveyorSpeed. 133 /// </summary> 134 /// <value>The liquid speed.</value> 135 [Description("传送带运行速度,越小,速度越快"), Category("自定义")] 136 public int ConveyorSpeed 137 { 138 get { return conveyorSpeed; } 139 set 140 { 141 if (value <= 0) 142 return; 143 conveyorSpeed = value; 144 m_timer.Interval = value; 145 } 146 } 147 148 /// <summary> 149 /// The m working rect 150 /// </summary> 151 Rectangle m_workingRect; 152 /// <summary> 153 /// The int line left 154 /// </summary> 155 int intLineLeft = 0; 156 /// <summary> 157 /// The m timer 158 /// </summary> 159 Timer m_timer; 160 /// <summary> 161 /// Initializes a new instance of the <see cref="UCConveyor"/> class. 162 /// </summary> 163 public UCConveyor() 164 { 165 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 166 this.SetStyle(ControlStyles.DoubleBuffer, true); 167 this.SetStyle(ControlStyles.ResizeRedraw, true); 168 this.SetStyle(ControlStyles.Selectable, true); 169 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 170 this.SetStyle(ControlStyles.UserPaint, true); 171 this.SizeChanged += UCConveyor_SizeChanged; 172 this.Size = new Size(300, 50); 173 m_timer = new Timer(); 174 m_timer.Interval = 100; 175 m_timer.Tick += timer_Tick; 176 m_timer.Enabled = true; 177 } 178 179 /// <summary> 180 /// Handles the Tick event of the timer control. 181 /// </summary> 182 /// <param name="sender">The source of the event.</param> 183 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> 184 void timer_Tick(object sender, EventArgs e) 185 { 186 intLineLeft += 2; 187 if (intLineLeft > 12) 188 intLineLeft = 0; 189 Refresh(); 190 } 191 192 /// <summary> 193 /// Handles the SizeChanged event of the UCConveyor control. 194 /// </summary> 195 /// <param name="sender">The source of the event.</param> 196 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> 197 void UCConveyor_SizeChanged(object sender, EventArgs e) 198 { 199 ResetWorkingRect(); 200 } 201 202 /// <summary> 203 /// Resets the working rect. 204 /// </summary> 205 private void ResetWorkingRect() 206 { 207 if (inclination == 90 || inclination == -90) 208 { 209 m_workingRect = new Rectangle((this.Width - conveyorHeight) / 2, 1, conveyorHeight, this.Height - 2); 210 } 211 else if (inclination == 0) 212 { 213 m_workingRect = new Rectangle(1, (this.Height - conveyorHeight) / 2 + 1, this.Width - 2, conveyorHeight); 214 } 215 else 216 { 217 //根据角度计算需要的高度 218 int intHeight = (int)(Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000)) * (this.Width)); 219 if (intHeight >= this.Height) 220 intHeight = this.Height; 221 222 int intWidth = (int)(intHeight / (Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000)))); 223 intHeight += conveyorHeight; 224 if (intHeight >= this.Height) 225 intHeight = this.Height; 226 m_workingRect = new Rectangle((this.Width - intWidth) / 2 + 1, (this.Height - intHeight) / 2 + 1, intWidth - 2, intHeight - 2); 227 } 228 229 } 230 231 /// <summary> 232 /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。 233 /// </summary> 234 /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param> 235 protected override void OnPaint(PaintEventArgs e) 236 { 237 base.OnPaint(e); 238 var g = e.Graphics; 239 g.SetGDIHigh(); 240 //g.FillRectangle(new SolidBrush(Color.FromArgb(100, conveyorColor)), m_workingRect); 241 242 //轴 243 //左端 244 var rectLeft = new Rectangle(m_workingRect.Left + 5, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top) + 5, conveyorHeight - 10, conveyorHeight - 10); 245 g.FillEllipse(new SolidBrush(conveyorColor), rectLeft); 246 g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectLeft.Left + (rectLeft.Width - 6) / 2, rectLeft.Top + (rectLeft.Height - 6) / 2, 6, 6)); 247 //右端 248 var rectRight = new Rectangle(m_workingRect.Right - conveyorHeight + 5, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)) + 5, conveyorHeight - 10, conveyorHeight - 10); 249 g.FillEllipse(new SolidBrush(conveyorColor), rectRight); 250 g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectRight.Left + (rectRight.Width - 6) / 2, rectRight.Top + (rectRight.Height - 6) / 2, 6, 6)); 251 252 253 //传送带 254 //左端 255 GraphicsPath path = new GraphicsPath(); 256 path.AddArc(new Rectangle(m_workingRect.Left, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top), conveyorHeight, conveyorHeight), 90F - (float)inclination, 180F); 257 //右端 258 path.AddArc(new Rectangle(m_workingRect.Right - conveyorHeight, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)), conveyorHeight, conveyorHeight), 270 - (float)inclination, 180F); 259 path.CloseAllFigures(); 260 g.DrawPath(new Pen(new SolidBrush(conveyorColor), 3), path); 261 262 //液体流动 263 if (ConveyorDirection != ConveyorDirection.None) 264 { 265 Pen p = new Pen(new SolidBrush(Color.FromArgb(150, this.BackColor)), 4); 266 p.DashPattern = new float[] { 6, 6 }; 267 p.DashOffset = intLineLeft * (ConveyorDirection == ConveyorDirection.Forward ? -1 : 1); 268 g.DrawPath(p, path); 269 } 270 } 271 } 272 273 /// <summary> 274 /// Enum ConveyorDirection 275 /// </summary> 276 public enum ConveyorDirection 277 { 278 /// <summary> 279 /// The none 280 /// </summary> 281 None, 282 /// <summary> 283 /// The forward 284 /// </summary> 285 Forward, 286 /// <summary> 287 /// The backward 288 /// </summary> 289 Backward 290 } 291 }
开始
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧