UserSwitch.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. namespace HslCommunication.Controls
  10. {
  11. /// <summary>
  12. /// 一个开关按钮类
  13. /// </summary>
  14. [DefaultEvent("Click")]
  15. public partial class UserSwitch : UserControl
  16. {
  17. /// <summary>
  18. /// 实例化一个开关按钮对象
  19. /// </summary>
  20. public UserSwitch()
  21. {
  22. InitializeComponent();
  23. DoubleBuffered = true;
  24. brush_switch_background = new SolidBrush(color_switch_background);
  25. pen_switch_background = new Pen(color_switch_background, 2f);
  26. brush_switch_foreground = new SolidBrush(color_switch_foreground);
  27. centerFormat = new StringFormat();
  28. centerFormat.Alignment = StringAlignment.Center;
  29. centerFormat.LineAlignment = StringAlignment.Center;
  30. }
  31. private void UserSwitch_Load(object sender, EventArgs e)
  32. {
  33. }
  34. private void UserSwitch_Paint(object sender, PaintEventArgs e)
  35. {
  36. e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  37. e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
  38. Point center = GetCenterPoint();
  39. e.Graphics.TranslateTransform(center.X, center.Y);
  40. int radius = 45 * (center.X * 2 - 30) / 130;
  41. if (radius < 5) return;
  42. Rectangle rectangle_larger = new Rectangle(-radius - 4, -radius - 4, 2 * radius + 8, 2 * radius + 8);
  43. Rectangle rectangle = new Rectangle(-radius, -radius, 2 * radius, 2 * radius);
  44. e.Graphics.DrawEllipse(pen_switch_background, rectangle_larger);
  45. e.Graphics.FillEllipse(brush_switch_background, rectangle);
  46. float angle = -36;
  47. if (SwitchStatus) angle = 36;
  48. e.Graphics.RotateTransform(angle);
  49. int temp = 20 * (center.X * 2 - 30) / 130;
  50. Rectangle rect_switch = new Rectangle(-center.X / 8, -radius - temp, center.X / 4, radius * 2 + temp * 2);
  51. e.Graphics.FillRectangle(brush_switch_foreground, rect_switch);
  52. Rectangle rect_mini = new Rectangle(-center.X / 16, -radius - 10, center.X / 8, center.X * 3 / 8);
  53. e.Graphics.FillEllipse(SwitchStatus ? Brushes.LimeGreen:Brushes.Tomato, rect_mini);
  54. Rectangle rect_text = new Rectangle(-50, -radius - temp - 15, 100, 15);
  55. e.Graphics.DrawString(SwitchStatus? description[1] : description[0], Font, SwitchStatus ? Brushes.LimeGreen : Brushes.Tomato, rect_text, centerFormat);
  56. e.Graphics.ResetTransform();
  57. }
  58. #region Private Member
  59. private Color color_switch_background = Color.DimGray; // 按钮的背景颜色,包括边线颜色
  60. private Brush brush_switch_background = null; // 按钮的背景画刷
  61. private Pen pen_switch_background = null; // 按钮的背景画笔
  62. private bool switch_status = false; // 按钮的开关状态
  63. private Color color_switch_foreground = Color.FromArgb(36, 36, 36); // 按钮开关的前景色
  64. private Brush brush_switch_foreground = null; // 按钮开关的前景色画刷
  65. private StringFormat centerFormat = null; // 居中显示的格式化文本
  66. private string[] description = new string[2] { "Off", "On" }; // 两种开关状态的文本描述
  67. #endregion
  68. #region Event Handle
  69. /// <summary>
  70. /// 开关按钮发生变化的事件
  71. /// </summary>
  72. [Category("操作")]
  73. [Description("点击了按钮开发后触发")]
  74. public event Action<object, bool> OnSwitchChanged;
  75. #endregion
  76. #region Private Method
  77. private Point GetCenterPoint()
  78. {
  79. if (Height > Width)
  80. {
  81. return new Point(Width / 2, Width / 2);
  82. }
  83. else
  84. {
  85. return new Point(Height / 2, Height / 2);
  86. }
  87. }
  88. #endregion
  89. #region Public Member
  90. /// <summary>
  91. /// 获取或设置开关按钮的背景色
  92. /// </summary>
  93. [Browsable(true)]
  94. [Description("获取或设置开关按钮的背景色")]
  95. [Category("外观")]
  96. [DefaultValue(typeof(Color), "DimGray")]
  97. public Color SwitchBackground
  98. {
  99. get
  100. {
  101. return color_switch_background;
  102. }
  103. set
  104. {
  105. color_switch_background = value;
  106. brush_switch_background?.Dispose();
  107. pen_switch_background?.Dispose();
  108. brush_switch_background = new SolidBrush(color_switch_background);
  109. pen_switch_background = new Pen(color_switch_background, 2f);
  110. Invalidate();
  111. }
  112. }
  113. /// <summary>
  114. /// 获取或设置开关按钮的前景色
  115. /// </summary>
  116. [Browsable(true)]
  117. [Description("获取或设置开关按钮的前景色")]
  118. [Category("外观")]
  119. [DefaultValue(typeof(Color), "[36, 36, 36]")]
  120. public Color SwitchForeground
  121. {
  122. get
  123. {
  124. return color_switch_foreground;
  125. }
  126. set
  127. {
  128. color_switch_foreground = value;
  129. brush_switch_foreground = new SolidBrush(color_switch_foreground);
  130. Invalidate();
  131. }
  132. }
  133. /// <summary>
  134. /// 获取或设置开关按钮的开合状态
  135. /// </summary>
  136. [Browsable(true)]
  137. [Description("获取或设置开关按钮的开合状态")]
  138. [Category("外观")]
  139. [DefaultValue(false)]
  140. public bool SwitchStatus
  141. {
  142. get
  143. {
  144. return switch_status;
  145. }
  146. set
  147. {
  148. if(value != switch_status)
  149. {
  150. switch_status = value;
  151. Invalidate();
  152. OnSwitchChanged?.Invoke(this, switch_status);
  153. }
  154. }
  155. }
  156. /// <summary>
  157. /// 获取或设置两种开关状态的文本描述,例如:new string[]{"Off","On"}
  158. /// </summary>
  159. [Browsable(false)]
  160. public string[] SwitchStatusDescription
  161. {
  162. get { return description; }
  163. set
  164. {
  165. if (value?.Length == 2)
  166. {
  167. description = value;
  168. }
  169. }
  170. }
  171. #endregion
  172. private void UserSwitch_Click(object sender, EventArgs e)
  173. {
  174. SwitchStatus = !SwitchStatus;
  175. }
  176. }
  177. }