1. 程式人生 > >(五十八)c#Winform自定義控制元件-管道閥門(工業)

(五十八)c#Winform自定義控制元件-管道閥門(工業)

前提

入行已經7,8年了,一直想做一套漂亮點的自定義控制元件,於是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果覺得寫的還行,請點個 star 支援一下吧

歡迎前來交流探討: 企鵝群568015492 

麻煩部落格下方點個【推薦】,謝謝

NuGet

Install-Package HZH_Controls

目錄

https://www.cnblogs.com/bfyx/p/11364884.html

用處及效果

準備工作

請先了解GDI+和三角函式

開始

新增一個類UCValve,繼承UserControl

新增一個閥門顯示樣式列舉

 1 /// <summary>
 2     /// Enum ValveStyle
 3     /// </summary>
 4     public enum ValveStyle
 5     {
 6         /// <summary>
 7         /// 橫向,開關在上方
 8         /// </summary>
 9         Horizontal_Top,
10         /// <summary>
11         /// 橫向,開關在下方
12         /// </summary>
13         Horizontal_Bottom,
14         /// <summary>
15         /// 縱向,開關在左側
16         /// </summary>
17         Vertical_Left,
18         /// <summary>
19         /// 縱向,開關在右側
20         /// </summary>
21         Vertical_Right,
22     }

新增一些屬性

  1  /// <summary>
  2         /// The valve style
  3         /// </summary>
  4         private ValveStyle valveStyle = ValveStyle.Horizontal_Top;
  5 
  6         /// <summary>
  7         /// Gets or sets the valve style.
  8         /// </summary>
  9         /// <value>The valve style.</value>
 10         [Description("閥門樣式"), Category("自定義")]
 11         public ValveStyle ValveStyle
 12         {
 13             get { return valveStyle; }
 14             set
 15             {
 16                 valveStyle = value;
 17                 Refresh();
 18             }
 19         }
 20 
 21         /// <summary>
 22         /// The valve color
 23         /// </summary>
 24         private Color valveColor = Color.FromArgb(255, 77, 59);
 25 
 26         /// <summary>
 27         /// Gets or sets the color of the valve.
 28         /// </summary>
 29         /// <value>The color of the valve.</value>
 30         [Description("閥門顏色"), Category("自定義")]
 31         public Color ValveColor
 32         {
 33             get { return valveColor; }
 34             set
 35             {
 36                 valveColor = value;
 37                 Refresh();
 38             }
 39         }
 40 
 41         /// <summary>
 42         /// The switch color
 43         /// </summary>
 44         private Color switchColor = Color.FromArgb(232, 30, 99);
 45 
 46         /// <summary>
 47         /// Gets or sets the color of the switch.
 48         /// </summary>
 49         /// <value>The color of the switch.</value>
 50         [Description("開關把手顏色"), Category("自定義")]
 51         public Color SwitchColor
 52         {
 53             get { return switchColor; }
 54             set
 55             {
 56                 switchColor = value;
 57                 Refresh();
 58             }
 59         }
 60 
 61         /// <summary>
 62         /// The axis color
 63         /// </summary>
 64         private Color axisColor = Color.FromArgb(3, 169, 243);
 65 
 66         /// <summary>
 67         /// Gets or sets the color of the axis.
 68         /// </summary>
 69         /// <value>The color of the axis.</value>
 70         [Description("軸顏色"), Category("自定義")]
 71         public Color AxisColor
 72         {
 73             get { return axisColor; }
 74             set
 75             {
 76                 axisColor = value;
 77                 Refresh();
 78             }
 79         }
 80 
 81         /// <summary>
 82         /// The asis bottom color
 83         /// </summary>
 84         private Color asisBottomColor = Color.FromArgb(3, 169, 243);
 85 
 86         /// <summary>
 87         /// Gets or sets the color of the asis bottom.
 88         /// </summary>
 89         /// <value>The color of the asis bottom.</value>
 90         [Description("軸底座顏色"), Category("自定義")]
 91         public Color AsisBottomColor
 92         {
 93             get { return asisBottomColor; }
 94             set { asisBottomColor = value; }
 95         }
 96 
 97         /// <summary>
 98         /// The opened
 99         /// </summary>
100         private bool opened = true;
101 
102         /// <summary>
103         /// Gets or sets a value indicating whether this <see cref="UCValve" /> is opened.
104         /// </summary>
105         /// <value><c>true</c> if opened; otherwise, <c>false</c>.</value>
106         [Description("是否開啟"), Category("自定義")]
107         public bool Opened
108         {
109             get { return opened; }
110             set
111             {
112                 opened = value;
113                 Refresh();
114             }
115         }
116 
117         /// <summary>
118         /// The liquid direction
119         /// </summary>
120         private LiquidDirection liquidDirection = LiquidDirection.Forward;
121 
122         /// <summary>
123         /// Gets or sets the liquid direction.
124         /// </summary>
125         /// <value>The liquid direction.</value>
126         [Description("液體流動方向"), Category("自定義")]
127         public LiquidDirection LiquidDirection
128         {
129             get { return liquidDirection; }
130             set
131             {
132                 liquidDirection = value;
133                 if (value == Conduit.LiquidDirection.None)
134                     m_timer.Enabled = false;
135                 else
136                     m_timer.Enabled = true;
137                 Refresh();
138             }
139         }
140 
141         /// <summary>
142         /// The liquid speed
143         /// </summary>
144         private int liquidSpeed = 100;
145 
146         /// <summary>
147         /// 液體流速,越小,速度越快Gets or sets the liquid speed.
148         /// </summary>
149         /// <value>The liquid speed.</value>
150         [Description("液體流速,越小,速度越快"), Category("自定義")]
151         public int LiquidSpeed
152         {
153             get { return liquidSpeed; }
154             set
155             {
156                 if (value <= 0)
157                     return;
158                 liquidSpeed = value;
159                 m_timer.Interval = value;
160             }
161         }
162 
163         /// <summary>
164         /// The liquid color
165         /// </summary>
166         private Color liquidColor = Color.FromArgb(3, 169, 243);
167 
168         /// <summary>
169         /// Gets or sets the color of the liquid.
170         /// </summary>
171         /// <value>The color of the liquid.</value>
172         [Description("液體顏色"), Category("自定義")]
173         public Color LiquidColor
174         {
175             get { return liquidColor; }
176             set
177             {
178                 liquidColor = value;
179                 if (liquidDirection != Conduit.LiquidDirection.None)
180                     Refresh();
181             }
182         }
183         /// <summary>
184         /// The m timer
185         /// </summary>
186         Timer m_timer;
187         /// <summary>
188         /// The int line left
189         /// </summary>
190         int intLineLeft = 0;

重繪

  1  protected override void OnPaint(PaintEventArgs e)
  2         {
  3             base.OnPaint(e);
  4             var g = e.Graphics;
  5             Rectangle rectGuan = Rectangle.Empty;//管道
  6             Rectangle rectJK1 = Rectangle.Empty;//介面1
  7             Rectangle rectJK2 = Rectangle.Empty;//介面2
  8             Rectangle rectZ = Rectangle.Empty;//軸
  9             GraphicsPath linePath = new GraphicsPath();//管道中心線
 10             GraphicsPath dzPath = new GraphicsPath();//軸底座
 11             GraphicsPath bsPath = new GraphicsPath();//開關把手
 12             switch (valveStyle)
 13             {
 14                 case ValveStyle.Horizontal_Top:
 15                     rectGuan = new Rectangle(0, this.Height / 2, this.Width, this.Height / 2 - this.Height / 8);
 16                     rectJK1 = new Rectangle(this.Height / 8, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
 17                     rectJK2 = new Rectangle(rectGuan.Right - this.Height / 8 - rectGuan.Height / 2, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
 18                     linePath.AddLine(new Point(rectGuan.Left - 10, rectGuan.Top + rectGuan.Height / 2), new Point(rectGuan.Right + 10, rectGuan.Top + rectGuan.Height / 2));
 19                     rectZ = new Rectangle(rectGuan.Left + (rectGuan.Width - rectGuan.Height / 4) / 2, 10, rectGuan.Height / 4, rectGuan.Top - 10);
 20                     Point[] psTop = new Point[]             
 21                     {
 22                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Top- this.Height / 8- 5 ),
 23                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Top- this.Height / 8- 5 ),
 24                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height)/2,rectGuan.Top+2 ),
 25                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height)/2,rectGuan.Top +2),
 26                     };
 27                     dzPath.AddLines(psTop);
 28                     dzPath.CloseAllFigures();
 29                     if (opened)
 30                     {
 31                         bsPath.AddLine(rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2, 10 + (rectGuan.Height / 3) / 2, rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2 + rectGuan.Height + 10, 10 + (rectGuan.Height / 3) / 2);
 32                     }
 33                     else
 34                     {
 35                         bsPath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2 - 3, 1), new Point(rectGuan.Left + rectGuan.Width / 2 + 4, rectGuan.Height + 10));
 36                     }
 37                     break;
 38                 case ValveStyle.Horizontal_Bottom:
 39                     rectGuan = new Rectangle(0, this.Height / 8, this.Width, this.Height / 2 - this.Height / 8);
 40                     rectJK1 = new Rectangle(this.Height / 8, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
 41                     rectJK2 = new Rectangle(rectGuan.Right - this.Height / 8 - rectGuan.Height / 2, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
 42                     linePath.AddLine(new Point(rectGuan.Left - 10, rectGuan.Top + rectGuan.Height / 2), new Point(rectGuan.Right + 10, rectGuan.Top + rectGuan.Height / 2));
 43                     rectZ = new Rectangle(rectGuan.Left + (rectGuan.Width - rectGuan.Height / 4) / 2, rectGuan.Bottom + 10, rectGuan.Height / 4, this.Height - 10 - (rectGuan.Bottom + 10));
 44                     Point[] psBottom = new Point[]             
 45                     {
 46                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Bottom+ this.Height / 8+ 5 ),
 47                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Bottom+ this.Height / 8+ 5 ),
 48                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height)/2,rectGuan.Bottom-2 ),
 49                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height)/2,rectGuan.Bottom-2),
 50                     };
 51                     dzPath.AddLines(psBottom);
 52                     dzPath.CloseAllFigures();
 53                     if (opened)
 54                     {
 55                         bsPath.AddLine(rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2, this.Height - (10 + (rectGuan.Height / 3) / 2), rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2 + rectGuan.Height + 10, this.Height - (10 + (rectGuan.Height / 3) / 2));
 56                     }
 57                     else
 58                     {
 59                         bsPath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2 - 3, this.Height - 1), new Point(rectGuan.Left + rectGuan.Width / 2 + 4, this.Height - (rectGuan.Height + 10)));
 60                     }
 61                     break;
 62                 case ValveStyle.Vertical_Left:
 63                     rectGuan = new Rectangle(this.Width / 8, 0, this.Width / 2 - this.Width / 8, this.Height);
 64                     rectJK1 = new Rectangle(0, this.Width / 8, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
 65                     rectJK2 = new Rectangle(0, this.Height - this.Width / 8 - rectGuan.Width / 2, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
 66                     linePath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Top - 10), new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Bottom + 10));
 67                     rectZ = new Rectangle(rectGuan.Right, rectGuan.Top + (rectGuan.Height - rectGuan.Width / 4) / 2, rectGuan.Right - 10, rectGuan.Width / 4);
 68                     Point[] psLeft = new Point[]             
 69                     {
 70                         new Point(rectGuan.Right+ this.Width / 8+ 5 ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2),
 71                         new Point(rectGuan.Right+ this.Width / 8+ 5 ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2+rectGuan.Width / 2),                      
 72                         new Point(rectGuan.Right-2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2+rectGuan.Width),
 73                         new Point(rectGuan.Right-2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2),
 74                     };
 75                     dzPath.AddLines(psLeft);
 76                     dzPath.CloseAllFigures();
 77                     if (opened)
 78                     {
 79                         bsPath.AddLine(this.Width - (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2, this.Width - (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2 + rectGuan.Width + 10);
 80                     }
 81                     else
 82                     {
 83                         bsPath.AddLine(new Point(this.Width - 1, rectGuan.Top + rectGuan.Height / 2 - 3), new Point(this.Width - (rectGuan.Width + 10), rectGuan.Top + rectGuan.Height / 2 + 4));
 84                     }
 85                     break;
 86                 case ValveStyle.Vertical_Right:
 87                     rectGuan = new Rectangle(this.Width - this.Width / 8 - (this.Width / 2 - this.Width / 8), 0, this.Width / 2 - this.Width / 8, this.Height);
 88                     rectJK1 = new Rectangle(this.Width - (rectGuan.Width + this.Width / 4), this.Width / 8, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
 89                     rectJK2 = new Rectangle(this.Width - (rectGuan.Width + this.Width / 4), this.Height - this.Width / 8 - rectGuan.Width / 2, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
 90                     linePath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Top - 10), new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Bottom + 10));
 91                     rectZ = new Rectangle(10, rectGuan.Top + (rectGuan.Height - rectGuan.Width / 4) / 2, rectGuan.Left-10, rectGuan.Width / 4);
 92                     Point[] psRight = new Point[]             
 93                     {
 94                         new Point(rectGuan.Left- (this.Width / 8+ 5) ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2),
 95                         new Point(rectGuan.Left-( this.Width / 8+ 5) ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2+rectGuan.Width / 2),                      
 96                         new Point(rectGuan.Left+2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2+rectGuan.Width),
 97                         new Point(rectGuan.Left+2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2),
 98                     };
 99                     dzPath.AddLines(psRight);
100                     dzPath.CloseAllFigures();
101 
102                     if (opened)
103                     {
104                         bsPath.AddLine( (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2, (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2 + rectGuan.Width + 10);
105                     }
106                     else
107                     {
108                         bsPath.AddLine(new Point( 1, rectGuan.Top + rectGuan.Height / 2 - 3), new Point( (rectGuan.Width + 10), rectGuan.Top + rectGuan.Height / 2 + 4));
109                     }
110                     break;
111             }
112 
113             //管道
114             g.FillRectangle(new SolidBrush(valveColor), rectGuan);
115             //介面
116             g.FillRectangle(new SolidBrush(valveColor), rectJK1);
117             g.FillRectangle(new SolidBrush(Color.FromArgb(40, Color.White)), rectJK1);
118             g.FillRectangle(new SolidBrush(valveColor), rectJK2);
119             g.FillRectangle(new SolidBrush(Color.FromArgb(40, Color.White)), rectJK2);
120 
121 
122             //高亮
123             int intCount = (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 2 / 4;
124             for (int i = 0; i < intCount; i++)
125             {
126                 int _penWidth = (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 2 - 4 * i;
127                 if (_penWidth <= 0)
128                     _penWidth = 1;
129                 g.DrawPath(new Pen(new SolidBrush(Color.FromArgb(40, Color.White.R, Color.White.G, Color.White.B)), _penWidth), linePath);
130                 if (_penWidth == 1)
131                     break;
132             }
133 
134             g.SetGDIHigh();
135             //軸
136             g.FillRectangle(new SolidBrush(axisColor), rectZ);
137 
138             //閥門底座           
139             g.FillPath(new SolidBrush(asisBottomColor), dzPath);
140             g.FillPath(new SolidBrush(Color.FromArgb(50, Color.White)), dzPath);
141 
142             //把手
143             g.DrawPath(new Pen(new SolidBrush(switchColor), (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 3), bsPath);
144 
145             //液體流動
146             if (opened)
147             {
148                 Pen p = new Pen(new SolidBrush(liquidColor), 4);
149                 p.DashPattern = new float[] { 6, 6 };
150                 p.DashOffset = intLineLeft * (LiquidDirection == Conduit.LiquidDirection.Forward ? -1 : 1);
151                 g.DrawPath(p, linePath);
152             }
153         }

全部程式碼

  1 // ***********************************************************************
  2 // Assembly         : HZH_Controls
  3 // Created          : 2019-09-06
  4 //
  5 // ***********************************************************************
  6 // <copyright file="UCValve.cs">
  7 //     Copyright by Huang Zhenghui(黃正輝) All, QQ group:568015492 QQ:623128629 Email:[email protected]
  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 HZH_Controls.Controls.Conduit;
 24 using System.ComponentModel;
 25 
 26 namespace HZH_Controls.Controls
 27 {
 28     /// <summary>
 29     /// Class UCValve.
 30     /// Implements the <see cref="System.Windows.Forms.UserControl" />
 31     /// </summary>
 32     /// <seealso cref="System.Windows.Forms.UserControl" />
 33     public class UCValve : UserControl
 34     {
 35         /// <summary>
 36         /// The valve style
 37         /// </summary>
 38         private ValveStyle valveStyle = ValveStyle.Horizontal_Top;
 39 
 40         /// <summary>
 41         /// Gets or sets the valve style.
 42         /// </summary>
 43         /// <value>The valve style.</value>
 44         [Description("閥門樣式"), Category("自定義")]
 45         public ValveStyle ValveStyle
 46         {
 47             get { return valveStyle; }
 48             set
 49             {
 50                 valveStyle = value;
 51                 Refresh();
 52             }
 53         }
 54 
 55         /// <summary>
 56         /// The valve color
 57         /// </summary>
 58         private Color valveColor = Color.FromArgb(255, 77, 59);
 59 
 60         /// <summary>
 61         /// Gets or sets the color of the valve.
 62         /// </summary>
 63         /// <value>The color of the valve.</value>
 64         [Description("閥門顏色"), Category("自定義")]
 65         public Color ValveColor
 66         {
 67             get { return valveColor; }
 68             set
 69             {
 70                 valveColor = value;
 71                 Refresh();
 72             }
 73         }
 74 
 75         /// <summary>
 76         /// The switch color
 77         /// </summary>
 78         private Color switchColor = Color.FromArgb(232, 30, 99);
 79 
 80         /// <summary>
 81         /// Gets or sets the color of the switch.
 82         /// </summary>
 83         /// <value>The color of the switch.</value>
 84         [Description("開關把手顏色"), Category("自定義")]
 85         public Color SwitchColor
 86         {
 87             get { return switchColor; }
 88             set
 89             {
 90                 switchColor = value;
 91                 Refresh();
 92             }
 93         }
 94 
 95         /// <summary>
 96         /// The axis color
 97         /// </summary>
 98         private Color axisColor = Color.FromArgb(3, 169, 243);
 99 
100         /// <summary>
101         /// Gets or sets the color of the axis.
102         /// </summary>
103         /// <value>The color of the axis.</value>
104         [Description("軸顏色"), Category("自定義")]
105         public Color AxisColor
106         {
107             get { return axisColor; }
108             set
109             {
110                 axisColor = value;
111                 Refresh();
112             }
113         }
114 
115         /// <summary>
116         /// The asis bottom color
117         /// </summary>
118         private Color asisBottomColor = Color.FromArgb(3, 169, 243);
119 
120         /// <summary>
121         /// Gets or sets the color of the asis bottom.
122         /// </summary>
123         /// <value>The color of the asis bottom.</value>
124         [Description("軸底座顏色"), Category("自定義")]
125         public Color AsisBottomColor
126         {
127             get { return asisBottomColor; }
128             set { asisBottomColor = value; }
129         }
130 
131         /// <summary>
132         /// The opened
133         /// </summary>
134         private bool opened = true;
135 
136         /// <summary>
137         /// Gets or sets a value indicating whether this <see cref="UCValve" /> is opened.
138         /// </summary>
139         /// <value><c>true</c> if opened; otherwise, <c>false</c>.</value>
140         [Description("是否開啟"), Category("自定義")]
141         public bool Opened
142         {
143             get { return opened; }
144             set
145             {
146                 opened = value;
147                 Refresh();
148             }
149         }
150 
151         /// <summary>
152         /// The liquid direction
153         /// </summary>
154         private LiquidDirection liquidDirection = LiquidDirection.Forward;
155 
156         /// <summary>
157         /// Gets or sets the liquid direction.
158         /// </summary>
159         /// <value>The liquid direction.</value>
160         [Description("液體流動方向"), Category("自定義")]
161         public LiquidDirection LiquidDirection
162         {
163             get { return liquidDirection; }
164             set
165             {
166                 liquidDirection = value;
167                 if (value == Conduit.LiquidDirection.None)
168                     m_timer.Enabled = false;
169                 else
170                     m_timer.Enabled = true;
171                 Refresh();
172             }
173         }
174 
175         /// <summary>
176         /// The liquid speed
177         /// </summary>
178         private int liquidSpeed = 100;
179 
180         /// <summary>
181         /// 液體流速,越小,速度越快Gets or sets the liquid speed.
182         /// </summary>
183         /// <value>The liquid speed.</value>
184         [Description("液體流速,越小,速度越快"), Category("自定義")]
185         public int LiquidSpeed
186         {
187             get { return liquidSpeed; }
188             set
189             {
190                 if (value <= 0)
191                     return;
192                 liquidSpeed = value;
193                 m_timer.Interval = value;
194             }
195         }
196 
197         /// <summary>
198         /// The liquid color
199         /// </summary>
200         private Color liquidColor = Color.FromArgb(3, 169, 243);
201 
202         /// <summary>
203         /// Gets or sets the color of the liquid.
204         /// </summary>
205         /// <value>The color of the liquid.</value>
206         [Description("液體顏色"), Category("自定義")]
207         public Color LiquidColor
208         {
209             get { return liquidColor; }
210             set
211             {
212                 liquidColor = value;
213                 if (liquidDirection != Conduit.LiquidDirection.None)
214                     Refresh();
215             }
216         }
217         /// <summary>
218         /// The m timer
219         /// </summary>
220         Timer m_timer;
221         /// <summary>
222         /// The int line left
223         /// </summary>
224         int intLineLeft = 0;
225 
226         /// <summary>
227         /// Initializes a new instance of the <see cref="UCValve" /> class.
228         /// </summary>
229         public UCValve()
230         {
231             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
232             this.SetStyle(ControlStyles.DoubleBuffer, true);
233             this.SetStyle(ControlStyles.ResizeRedraw, true);
234             this.SetStyle(ControlStyles.Selectable, true);
235             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
236             this.SetStyle(ControlStyles.UserPaint, true);
237             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
238             this.Size = new Size(120, 100);
239             m_timer = new Timer();
240             m_timer.Interval = 100;
241             m_timer.Tick += timer_Tick;
242             m_timer.Enabled = true;
243         }
244 
245         /// <summary>
246         /// Handles the Tick event of the timer control.
247         /// </summary>
248         /// <param name="sender">The source of the event.</param>
249         /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
250         void timer_Tick(object sender, EventArgs e)
251         {
252             intLineLeft += 2;
253             if (intLineLeft > 12)
254                 intLineLeft = 0;
255             Refresh();
256         }
257 
258 
259         /// <summary>
260         /// 引發 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
261         /// </summary>
262         /// <param name="e">包含事件資料的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
263         protected override void OnPaint(PaintEventArgs e)
264         {
265             base.OnPaint(e);
266             var g = e.Graphics;
267             Rectangle rectGuan = Rectangle.Empty;//管道
268             Rectangle rectJK1 = Rectangle.Empty;//介面1
269             Rectangle rectJK2 = Rectangle.Empty;//介面2
270             Rectangle rectZ = Rectangle.Empty;//軸
271             GraphicsPath linePath = new GraphicsPath();//管道中心線
272             GraphicsPath dzPath = new GraphicsPath();//軸底座
273             GraphicsPath bsPath = new GraphicsPath();//開關把手
274             switch (valveStyle)
275             {
276                 case ValveStyle.Horizontal_Top:
277                     rectGuan = new Rectangle(0, this.Height / 2, this.Width, this.Height / 2 - this.Height / 8);
278                     rectJK1 = new Rectangle(this.Height / 8, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
279                     rectJK2 = new Rectangle(rectGuan.Right - this.Height / 8 - rectGuan.Height / 2, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
280                     linePath.AddLine(new Point(rectGuan.Left - 10, rectGuan.Top + rectGuan.Height / 2), new Point(rectGuan.Right + 10, rectGuan.Top + rectGuan.Height / 2));
281                     rectZ = new Rectangle(rectGuan.Left + (rectGuan.Width - rectGuan.Height / 4) / 2, 10, rectGuan.Height / 4, rectGuan.Top - 10);
282                     Point[] psTop = new Point[]             
283                     {
284                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Top- this.Height / 8- 5 ),
285                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Top- this.Height / 8- 5 ),
286                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height)/2,rectGuan.Top+2 ),
287                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height)/2,rectGuan.Top +2),
288                     };
289                     dzPath.AddLines(psTop);
290                     dzPath.CloseAllFigures();
291                     if (opened)
292                     {
293                         bsPath.AddLine(rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2, 10 + (rectGuan.Height / 3) / 2, rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2 + rectGuan.Height + 10, 10 + (rectGuan.Height / 3) / 2);
294                     }
295                     else
296                     {
297                         bsPath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2 - 3, 1), new Point(rectGuan.Left + rectGuan.Width / 2 + 4, rectGuan.Height + 10));
298                     }
299                     break;
300                 case ValveStyle.Horizontal_Bottom:
301                     rectGuan = new Rectangle(0, this.Height / 8, this.Width, this.Height / 2 - this.Height / 8);
302                     rectJK1 = new Rectangle(this.Height / 8, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
303                     rectJK2 = new Rectangle(rectGuan.Right - this.Height / 8 - rectGuan.Height / 2, rectGuan.Top - this.Height / 8, rectGuan.Height / 2, rectGuan.Height + this.Height / 4);
304                     linePath.AddLine(new Point(rectGuan.Left - 10, rectGuan.Top + rectGuan.Height / 2), new Point(rectGuan.Right + 10, rectGuan.Top + rectGuan.Height / 2));
305                     rectZ = new Rectangle(rectGuan.Left + (rectGuan.Width - rectGuan.Height / 4) / 2, rectGuan.Bottom + 10, rectGuan.Height / 4, this.Height - 10 - (rectGuan.Bottom + 10));
306                     Point[] psBottom = new Point[]             
307                     {
308                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Bottom+ this.Height / 8+ 5 ),
309                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height/2)/2,rectGuan.Bottom+ this.Height / 8+ 5 ),
310                         new Point(rectGuan.Right-(rectGuan.Width-rectGuan.Height)/2,rectGuan.Bottom-2 ),
311                         new Point(rectGuan.Left+(rectGuan.Width-rectGuan.Height)/2,rectGuan.Bottom-2),
312                     };
313                     dzPath.AddLines(psBottom);
314                     dzPath.CloseAllFigures();
315                     if (opened)
316                     {
317                         bsPath.AddLine(rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2, this.Height - (10 + (rectGuan.Height / 3) / 2), rectGuan.Left + (rectGuan.Width - rectGuan.Height - 10) / 2 + rectGuan.Height + 10, this.Height - (10 + (rectGuan.Height / 3) / 2));
318                     }
319                     else
320                     {
321                         bsPath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2 - 3, this.Height - 1), new Point(rectGuan.Left + rectGuan.Width / 2 + 4, this.Height - (rectGuan.Height + 10)));
322                     }
323                     break;
324                 case ValveStyle.Vertical_Left:
325                     rectGuan = new Rectangle(this.Width / 8, 0, this.Width / 2 - this.Width / 8, this.Height);
326                     rectJK1 = new Rectangle(0, this.Width / 8, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
327                     rectJK2 = new Rectangle(0, this.Height - this.Width / 8 - rectGuan.Width / 2, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
328                     linePath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Top - 10), new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Bottom + 10));
329                     rectZ = new Rectangle(rectGuan.Right, rectGuan.Top + (rectGuan.Height - rectGuan.Width / 4) / 2, rectGuan.Right - 10, rectGuan.Width / 4);
330                     Point[] psLeft = new Point[]             
331                     {
332                         new Point(rectGuan.Right+ this.Width / 8+ 5 ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2),
333                         new Point(rectGuan.Right+ this.Width / 8+ 5 ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2+rectGuan.Width / 2),                      
334                         new Point(rectGuan.Right-2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2+rectGuan.Width),
335                         new Point(rectGuan.Right-2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2),
336                     };
337                     dzPath.AddLines(psLeft);
338                     dzPath.CloseAllFigures();
339                     if (opened)
340                     {
341                         bsPath.AddLine(this.Width - (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2, this.Width - (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2 + rectGuan.Width + 10);
342                     }
343                     else
344                     {
345                         bsPath.AddLine(new Point(this.Width - 1, rectGuan.Top + rectGuan.Height / 2 - 3), new Point(this.Width - (rectGuan.Width + 10), rectGuan.Top + rectGuan.Height / 2 + 4));
346                     }
347                     break;
348                 case ValveStyle.Vertical_Right:
349                     rectGuan = new Rectangle(this.Width - this.Width / 8 - (this.Width / 2 - this.Width / 8), 0, this.Width / 2 - this.Width / 8, this.Height);
350                     rectJK1 = new Rectangle(this.Width - (rectGuan.Width + this.Width / 4), this.Width / 8, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
351                     rectJK2 = new Rectangle(this.Width - (rectGuan.Width + this.Width / 4), this.Height - this.Width / 8 - rectGuan.Width / 2, rectGuan.Width + this.Width / 4, rectGuan.Width / 2);
352                     linePath.AddLine(new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Top - 10), new Point(rectGuan.Left + rectGuan.Width / 2, rectGuan.Bottom + 10));
353                     rectZ = new Rectangle(10, rectGuan.Top + (rectGuan.Height - rectGuan.Width / 4) / 2, rectGuan.Left-10, rectGuan.Width / 4);
354                     Point[] psRight = new Point[]             
355                     {
356                         new Point(rectGuan.Left- (this.Width / 8+ 5) ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2),
357                         new Point(rectGuan.Left-( this.Width / 8+ 5) ,rectGuan.Top + (rectGuan.Height - rectGuan.Width / 2) / 2+rectGuan.Width / 2),                      
358                         new Point(rectGuan.Left+2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2+rectGuan.Width),
359                         new Point(rectGuan.Left+2, rectGuan.Top +(rectGuan.Height-rectGuan.Width)/2),
360                     };
361                     dzPath.AddLines(psRight);
362                     dzPath.CloseAllFigures();
363 
364                     if (opened)
365                     {
366                         bsPath.AddLine( (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2, (10 + (rectGuan.Width / 3) / 2), rectGuan.Top + (rectGuan.Height - rectGuan.Width - 10) / 2 + rectGuan.Width + 10);
367                     }
368                     else
369                     {
370                         bsPath.AddLine(new Point( 1, rectGuan.Top + rectGuan.Height / 2 - 3), new Point( (rectGuan.Width + 10), rectGuan.Top + rectGuan.Height / 2 + 4));
371                     }
372                     break;
373             }
374 
375             //管道
376             g.FillRectangle(new SolidBrush(valveColor), rectGuan);
377             //介面
378             g.FillRectangle(new SolidBrush(valveColor), rectJK1);
379             g.FillRectangle(new SolidBrush(Color.FromArgb(40, Color.White)), rectJK1);
380             g.FillRectangle(new SolidBrush(valveColor), rectJK2);
381             g.FillRectangle(new SolidBrush(Color.FromArgb(40, Color.White)), rectJK2);
382 
383 
384             //高亮
385             int intCount = (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 2 / 4;
386             for (int i = 0; i < intCount; i++)
387             {
388                 int _penWidth = (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 2 - 4 * i;
389                 if (_penWidth <= 0)
390                     _penWidth = 1;
391                 g.DrawPath(new Pen(new SolidBrush(Color.FromArgb(40, Color.White.R, Color.White.G, Color.White.B)), _penWidth), linePath);
392                 if (_penWidth == 1)
393                     break;
394             }
395 
396             g.SetGDIHigh();
397             //軸
398             g.FillRectangle(new SolidBrush(axisColor), rectZ);
399 
400             //閥門底座           
401             g.FillPath(new SolidBrush(asisBottomColor), dzPath);
402             g.FillPath(new SolidBrush(Color.FromArgb(50, Color.White)), dzPath);
403 
404             //把手
405             g.DrawPath(new Pen(new SolidBrush(switchColor), (valveStyle.ToString().StartsWith("H") ? rectGuan.Height : rectGuan.Width) / 3), bsPath);
406 
407             //液體流動
408             if (opened)
409             {
410                 Pen p = new Pen(new SolidBrush(liquidColor), 4);
411                 p.DashPattern = new float[] { 6, 6 };
412                 p.DashOffset = intLineLeft * (LiquidDirection == Conduit.LiquidDirection.Forward ? -1 : 1);
413                 g.DrawPath(p, linePath);
414             }
415         }
416     }
417 
418     /// <summary>
419     /// Enum ValveStyle
420     /// </summary>
421     public enum ValveStyle
422     {
423         /// <summary>
424         /// 橫向,開關在上方
425         /// </summary>
426         Horizontal_Top,
427         /// <summary>
428         /// 橫向,開關在下方
429         /// </summary>
430         Horizontal_Bottom,
431         /// <summary>
432         /// 縱向,開關在左側
433         /// </summary>
434         Vertical_Left,
435         /// <summary>
436         /// 縱向,開關在右側
437         /// </summary>
438         Vertical_Right,
439     }
440 }
View Code

 

最後的話

如果你喜歡的話,請到 https://gitee.com/kwwwvagaa/net_winform_custom_control 點個星星吧