UCValve.cs 20 KB

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