入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
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 点个星星吧