UCTrackBar.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. using System;
  2. using System.Windows.Forms;
  3. using System.Drawing;
  4. using System.ComponentModel;
  5. namespace PaintDotNet.CustomControl
  6. {
  7. public partial class UCTrackBar : Control
  8. {
  9. [Description("Left值改变事件"), Category("自定义")]
  10. public event EventHandler Value1Changed;
  11. [Description("Center值改变事件"), Category("自定义")]
  12. public event EventHandler Value2Changed;
  13. [Description("Right值改变事件"), Category("自定义")]
  14. public event EventHandler Value3Changed;
  15. [Description("鼠标抬起事件"), Category("自定义")]
  16. public event EventHandler ValueMouseUp;
  17. private int dcimalDigits = 0;
  18. [Description("值小数精确位数"), Category("自定义")]
  19. public int DcimalDigits
  20. {
  21. get { return dcimalDigits; }
  22. set { dcimalDigits = value; }
  23. }
  24. private float lineWidth = 10;
  25. [Description("线宽度"), Category("自定义")]
  26. public float LineWidth
  27. {
  28. get { return lineWidth; }
  29. set { lineWidth = value; }
  30. }
  31. private float minValue = 0;
  32. [Description("最小值"), Category("自定义")]
  33. public float MinValue
  34. {
  35. get { return minValue; }
  36. set
  37. {
  38. if (minValue > m1_value)
  39. return;
  40. if (minValue > m2_value)
  41. return;
  42. if (minValue > m3_value)
  43. return;
  44. minValue = value;
  45. this.Refresh();
  46. }
  47. }
  48. private float maxValue = 255;//256;
  49. [Description("最大值"), Category("自定义")]
  50. public float MaxValue
  51. {
  52. get { return maxValue; }
  53. set
  54. {
  55. if (value < m1_value)
  56. return;
  57. if (value < m2_value)
  58. return;
  59. if (value < m3_value)
  60. return;
  61. maxValue = value;
  62. this.Refresh();
  63. }
  64. }
  65. private float m1_value = 0;//2;//0;
  66. private float m2_value = 127;//128;
  67. private float m3_value = 255;//254;//256;
  68. [Description("Left值"), Category("自定义")]
  69. public float Value1
  70. {
  71. get { return this.m1_value; }
  72. set
  73. {
  74. if (value > maxValue || value < minValue)
  75. return;
  76. var v = (float)Math.Round((double)value, dcimalDigits);
  77. if (this.m1_value == v)
  78. return;
  79. this.m1_value = v;
  80. }
  81. }
  82. [Description("Center值"), Category("自定义")]
  83. public float Value2
  84. {
  85. get { return this.m2_value; }
  86. set
  87. {
  88. if (value > maxValue || value < minValue)
  89. return;
  90. var v = (float)Math.Round((double)value, dcimalDigits);
  91. if (this.m2_value == v)
  92. return;
  93. this.m2_value = v;
  94. //this.Refresh();
  95. //if (Value2Changed != null)
  96. //{
  97. // Value2Changed(this, null);
  98. //}
  99. }
  100. }
  101. [Description("Right值"), Category("自定义")]
  102. public float Value3
  103. {
  104. get { return this.m3_value; }
  105. set
  106. {
  107. if (value > maxValue || value < minValue)
  108. return;
  109. var v = (float)Math.Round((double)value, dcimalDigits);
  110. if (this.m3_value == v)
  111. return;
  112. this.m3_value = v;
  113. //this.Refresh();
  114. //if (Value3Changed != null)
  115. //{
  116. // Value3Changed(this, null);
  117. //}
  118. }
  119. }
  120. private Color m_lineColor = Color.FromArgb(255, 77, 59);
  121. [Description("线颜色"), Category("自定义")]
  122. public Color LineColor
  123. {
  124. get { return m_lineColor; }
  125. set
  126. {
  127. m_lineColor = value;
  128. this.Refresh();
  129. }
  130. }
  131. RectangleF m_lineRectangle;
  132. RectangleF m1_trackRectangle;
  133. RectangleF m2_trackRectangle;
  134. RectangleF m3_trackRectangle;
  135. public UCTrackBar()
  136. {
  137. this.Size = new Size(250, 30);
  138. this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  139. this.SetStyle(ControlStyles.DoubleBuffer, true);
  140. this.SetStyle(ControlStyles.ResizeRedraw, true);
  141. this.SetStyle(ControlStyles.Selectable, true);
  142. this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
  143. this.SetStyle(ControlStyles.UserPaint, true);
  144. this.MouseDown += UCTrackBar_MouseDown;
  145. this.MouseMove += UCTrackBar_MouseMove;
  146. this.MouseUp += UCTrackBar_MouseUp;
  147. }
  148. bool bln1Down = false;
  149. bool bln2Down = false;
  150. bool bln3Down = false;
  151. void UCTrackBar_MouseDown(object sender, MouseEventArgs e)
  152. {
  153. float locationValue = ((float)e.Location.X / (float)this.Width) * (maxValue - minValue);
  154. if (Math.Abs(locationValue - m3_value) < 2 || Math.Abs(locationValue - m2_value) < 2 || Math.Abs(locationValue - m1_value) < 2 ||/*m_lineRectangle.Contains(e.Location) ||*/ m1_trackRectangle.Contains(e.Location) || m2_trackRectangle.Contains(e.Location) || m3_trackRectangle.Contains(e.Location))
  155. {
  156. float minValue = Math.Min(Math.Abs(locationValue - m3_value), Math.Min(Math.Abs(locationValue - m2_value), Math.Abs(locationValue - m1_value)));
  157. if (Math.Abs(locationValue - m3_value) == minValue)
  158. {
  159. bln3Down = true;
  160. bln2Down = false;
  161. bln1Down = false;
  162. }
  163. //Value = ((float)e.Location.X / (float)this.Width) * (maxValue - minValue);
  164. else if (Math.Abs(locationValue - m2_value) == minValue)
  165. {
  166. bln2Down = true;
  167. bln3Down = false;
  168. bln1Down = false;
  169. }
  170. else if (Math.Abs(locationValue - m1_value) == minValue)
  171. {
  172. bln1Down = true;
  173. bln2Down = false;
  174. bln3Down = false;
  175. }
  176. }
  177. }
  178. void UCTrackBar_MouseMove(object sender, MouseEventArgs e)
  179. {
  180. if (bln1Down)
  181. {
  182. float value = ((float)e.Location.X / (float)this.Width) * (maxValue - minValue);
  183. if (value > maxValue || value < minValue)
  184. return;
  185. Value1 = Math.Min(value, Value2 - 1);
  186. this.Refresh();
  187. if (Value1Changed != null)
  188. {
  189. Value1Changed(this, null);
  190. }
  191. }
  192. if (bln2Down)
  193. {
  194. float value = ((float)e.Location.X / (float)this.Width) * (maxValue - minValue);
  195. if (value > maxValue || value < minValue)
  196. return;
  197. Value2 = Math.Max(Value1 + 1, Math.Min(value, Value3 - 1));
  198. this.Refresh();
  199. if (Value2Changed != null)
  200. {
  201. Value2Changed(this, null);
  202. }
  203. }
  204. if (bln3Down)
  205. {
  206. float value = ((float)e.Location.X / (float)this.Width) * (maxValue - minValue);
  207. if (value > maxValue || value < minValue)
  208. return;
  209. Value3 = Math.Max(value, Value2 + 1);
  210. this.Refresh();
  211. if (Value3Changed != null)
  212. {
  213. Value3Changed(this, null);
  214. }
  215. }
  216. }
  217. void UCTrackBar_MouseUp(object sender, MouseEventArgs e)
  218. {
  219. bln1Down = false;
  220. bln2Down = false;
  221. bln3Down = false;
  222. if (ValueMouseUp != null)
  223. {
  224. ValueMouseUp(this, null);
  225. }
  226. }
  227. protected override void OnPaint(PaintEventArgs e)
  228. {
  229. base.OnPaint(e);
  230. Graphics g = e.Graphics;
  231. //g.SetGDIHigh();
  232. m_lineRectangle = new RectangleF(lineWidth, (this.Size.Height - lineWidth) / 2, this.Size.Width - lineWidth * 2, lineWidth);
  233. ////GraphicsPath pathLine = ControlHelper.CreateRoundedRectanglePath(m_lineRectangle, 5);
  234. ////g.FillPath(new SolidBrush(m_lineColor), pathLine);
  235. //m_trackRectangle = new RectangleF(m_lineRectangle.Left - lineWidth + (((float)m_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)), (this.Size.Height - lineWidth * 2) / 2, lineWidth * 2 - 4, lineWidth * 2 - 4);
  236. m1_trackRectangle = new RectangleF(m_lineRectangle.Left - lineWidth + (((float)m1_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)), (this.Size.Height - lineWidth * 2) / 2, lineWidth * 2 - 4, lineWidth * 2 - 4);
  237. m2_trackRectangle = new RectangleF(m_lineRectangle.Left - lineWidth + (((float)m2_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)), (this.Size.Height - lineWidth * 2) / 2, lineWidth * 2 - 4, lineWidth * 2 - 4);
  238. m3_trackRectangle = new RectangleF(m_lineRectangle.Left - lineWidth + (((float)m3_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)), (this.Size.Height - lineWidth * 2) / 2, lineWidth * 2 - 4, lineWidth * 2 - 4);
  239. ////m_trackRectangle -= 4;
  240. //g.FillEllipse(new SolidBrush(m_lineColor), m1_trackRectangle);
  241. //g.FillEllipse(new SolidBrush(m_lineColor), m2_trackRectangle);
  242. //g.FillEllipse(new SolidBrush(m_lineColor), m3_trackRectangle);
  243. //g.FillEllipse(Brushes.White, new RectangleF(m1_trackRectangle.X + m1_trackRectangle.Width / 4, m1_trackRectangle.Y + m1_trackRectangle.Height / 4, m1_trackRectangle.Width / 2, m1_trackRectangle.Height / 2));
  244. //g.FillEllipse(Brushes.White, new RectangleF(m2_trackRectangle.X + m2_trackRectangle.Width / 4, m2_trackRectangle.Y + m2_trackRectangle.Height / 4, m2_trackRectangle.Width / 2, m2_trackRectangle.Height / 2));
  245. //g.FillEllipse(Brushes.White, new RectangleF(m3_trackRectangle.X + m3_trackRectangle.Width / 4, m3_trackRectangle.Y + m3_trackRectangle.Height / 4, m3_trackRectangle.Width / 2, m3_trackRectangle.Height / 2));
  246. Brush brush = Brushes.Black;
  247. //Pen pen = (Pen)Pens.Gray.Clone();
  248. //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
  249. int triangleHalfLength = 7;// 3 * 2;
  250. int triangleSize = 13;
  251. int pos1 = triangleHalfLength + (int)(m_lineRectangle.Left - lineWidth + (((float)m1_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)));
  252. int pos2 = triangleHalfLength + (int)(m_lineRectangle.Left - lineWidth + (((float)m2_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)));
  253. int pos3 = triangleHalfLength + (int)(m_lineRectangle.Left - lineWidth + (((float)m3_value / (float)(maxValue - minValue)) * (this.Size.Width - lineWidth * 2)));
  254. Point a1 = new Point(pos1 - triangleHalfLength, triangleSize - 1);
  255. Point b1 = new Point(pos1, 0);
  256. Point c1 = new Point(pos1 + triangleHalfLength, triangleSize - 1);
  257. //Point a2 = new Point(a1.X, Height - 1 - a1.Y);
  258. //Point b2 = new Point(b1.X, Height - 1 - b1.Y);
  259. //Point c2 = new Point(c1.X, Height - 1 - c1.Y);
  260. Point a2 = new Point(pos2 - triangleHalfLength, triangleSize - 1);
  261. Point b2 = new Point(pos2, 0);
  262. Point c2 = new Point(pos2 + triangleHalfLength, triangleSize - 1);
  263. Point a3 = new Point(pos3 - triangleHalfLength, triangleSize - 1);
  264. Point b3 = new Point(pos3, 0);
  265. Point c3 = new Point(pos3 + triangleHalfLength, triangleSize - 1);
  266. g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 });
  267. g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 });
  268. g.FillPolygon(brush, new Point[] { a3, b3, c3, a3 });
  269. //if (this.drawNearNub)
  270. //{
  271. // g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 });
  272. //}
  273. //if (this.drawFarNub)
  274. //{
  275. // g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 });
  276. //}
  277. }
  278. }
  279. }
  280. //原文链接:https://blog.csdn.net/kwwwvagaa/article/details/100622682