前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
官网:https://www.hzhcontrols.cn
GitHub:https://github.com/kwwwvagaa/NetWinformControl
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
目录
c#Winform自定义控件-目录_c#winform自定义控件-有图标的按钮-CSDN博客
用处及效果
准备工作
依然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 }
完整代码
// ***********************************************************************
// Assembly : HZH_Controls
// Created : 2019-09-05
//
// ***********************************************************************
// <copyright file="UCConveyor.cs">
// Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
// </copyright>
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
namespace HZH_Controls.Controls
{
/// <summary>
/// Class UCConveyor.
/// Implements the <see cref="System.Windows.Forms.UserControl" />
/// </summary>
/// <seealso cref="System.Windows.Forms.UserControl" />
public class UCConveyor : UserControl
{
/// <summary>
/// The conveyor color
/// </summary>
private Color conveyorColor = Color.FromArgb(255, 77, 59);
/// <summary>
/// Gets or sets the color of the conveyor.
/// </summary>
/// <value>The color of the conveyor.</value>
[Description("传送带颜色"), Category("自定义")]
public Color ConveyorColor
{
get { return conveyorColor; }
set
{
conveyorColor = value;
Refresh();
}
}
/// <summary>
/// The inclination
/// </summary>
private double inclination = 0;
/// <summary>
/// Gets or sets the inclination.
/// </summary>
/// <value>The inclination.</value>
[Description("传送带角度(-90<=value<=90)"), Category("自定义")]
public double Inclination
{
get { return inclination; }
set
{
if (value > 90 || value < -90)
return;
inclination = value;
ResetWorkingRect();
Refresh();
}
}
/// <summary>
/// The conveyor height
/// </summary>
private int conveyorHeight = 50;
/// <summary>
/// Gets or sets the height of the conveyor.
/// </summary>
/// <value>The height of the conveyor.</value>
[Description("传送带高度"), Category("自定义")]
public int ConveyorHeight
{
get { return conveyorHeight; }
set
{
conveyorHeight = value;
ResetWorkingRect();
Refresh();
}
}
/// <summary>
/// The conveyor direction
/// </summary>
private ConveyorDirection conveyorDirection = ConveyorDirection.Forward;
/// <summary>
/// Gets or sets the conveyor direction.
/// </summary>
/// <value>The conveyor direction.</value>
[Description("传送带运行方向"), Category("自定义")]
public ConveyorDirection ConveyorDirection
{
get { return conveyorDirection; }
set
{
conveyorDirection = value;
if (value == HZH_Controls.Controls.ConveyorDirection.None)
{
m_timer.Enabled = false;
Refresh();
}
else
{
m_timer.Enabled = true;
}
}
}
/// <summary>
/// The liquid speed
/// </summary>
private int conveyorSpeed = 100;
/// <summary>
/// 传送带运行速度,越小,速度越快Gets or sets the ConveyorSpeed.
/// </summary>
/// <value>The liquid speed.</value>
[Description("传送带运行速度,越小,速度越快"), Category("自定义")]
public int ConveyorSpeed
{
get { return conveyorSpeed; }
set
{
if (value <= 0)
return;
conveyorSpeed = value;
m_timer.Interval = value;
}
}
/// <summary>
/// The m working rect
/// </summary>
Rectangle m_workingRect;
/// <summary>
/// The int line left
/// </summary>
int intLineLeft = 0;
/// <summary>
/// The m timer
/// </summary>
Timer m_timer;
/// <summary>
/// Initializes a new instance of the <see cref="UCConveyor"/> class.
/// </summary>
public UCConveyor()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SizeChanged += UCConveyor_SizeChanged;
this.Size = new Size(300, 50);
m_timer = new Timer();
m_timer.Interval = 100;
m_timer.Tick += timer_Tick;
m_timer.Enabled = true;
}
/// <summary>
/// Handles the Tick event of the timer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
void timer_Tick(object sender, EventArgs e)
{
intLineLeft += 2;
if (intLineLeft > 12)
intLineLeft = 0;
Refresh();
}
/// <summary>
/// Handles the SizeChanged event of the UCConveyor control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
void UCConveyor_SizeChanged(object sender, EventArgs e)
{
ResetWorkingRect();
}
/// <summary>
/// Resets the working rect.
/// </summary>
private void ResetWorkingRect()
{
if (inclination == 90 || inclination == -90)
{
m_workingRect = new Rectangle((this.Width - conveyorHeight) / 2, 1, conveyorHeight, this.Height - 2);
}
else if (inclination == 0)
{
m_workingRect = new Rectangle(1, (this.Height - conveyorHeight) / 2 + 1, this.Width - 2, conveyorHeight);
}
else
{
//根据角度计算需要的高度
int intHeight = (int)(Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000)) * (this.Width));
if (intHeight >= this.Height)
intHeight = this.Height;
int intWidth = (int)(intHeight / (Math.Tan(Math.PI * (Math.Abs(inclination) / 180.00000))));
intHeight += conveyorHeight;
if (intHeight >= this.Height)
intHeight = this.Height;
m_workingRect = new Rectangle((this.Width - intWidth) / 2 + 1, (this.Height - intHeight) / 2 + 1, intWidth - 2, intHeight - 2);
}
}
/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SetGDIHigh();
//g.FillRectangle(new SolidBrush(Color.FromArgb(100, conveyorColor)), m_workingRect);
//轴
//左端
var rectLeft = new Rectangle(m_workingRect.Left + 5, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top) + 5, conveyorHeight - 10, conveyorHeight - 10);
g.FillEllipse(new SolidBrush(conveyorColor), rectLeft);
g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectLeft.Left + (rectLeft.Width - 6) / 2, rectLeft.Top + (rectLeft.Height - 6) / 2, 6, 6));
//右端
var rectRight = new Rectangle(m_workingRect.Right - conveyorHeight + 5, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)) + 5, conveyorHeight - 10, conveyorHeight - 10);
g.FillEllipse(new SolidBrush(conveyorColor), rectRight);
g.FillEllipse(new SolidBrush(Color.White), new Rectangle(rectRight.Left + (rectRight.Width - 6) / 2, rectRight.Top + (rectRight.Height - 6) / 2, 6, 6));
//传送带
//左端
GraphicsPath path = new GraphicsPath();
path.AddArc(new Rectangle(m_workingRect.Left, (inclination >= 0 ? (m_workingRect.Bottom - conveyorHeight) : m_workingRect.Top), conveyorHeight, conveyorHeight), 90F - (float)inclination, 180F);
//右端
path.AddArc(new Rectangle(m_workingRect.Right - conveyorHeight, (inclination >= 0 ? (m_workingRect.Top) : (m_workingRect.Bottom - conveyorHeight)), conveyorHeight, conveyorHeight), 270 - (float)inclination, 180F);
path.CloseAllFigures();
g.DrawPath(new Pen(new SolidBrush(conveyorColor), 3), path);
//液体流动
if (ConveyorDirection != ConveyorDirection.None)
{
Pen p = new Pen(new SolidBrush(Color.FromArgb(150, this.BackColor)), 4);
p.DashPattern = new float[] { 6, 6 };
p.DashOffset = intLineLeft * (ConveyorDirection == ConveyorDirection.Forward ? -1 : 1);
g.DrawPath(p, path);
}
}
}
/// <summary>
/// Enum ConveyorDirection
/// </summary>
public enum ConveyorDirection
{
/// <summary>
/// The none
/// </summary>
None,
/// <summary>
/// The forward
/// </summary>
Forward,
/// <summary>
/// The backward
/// </summary>
Backward
}
}