前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
前提
入行已經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+和三角函數
開始
添加一個類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;