终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

285 lines
13 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Data;
  11. using System.Windows.Documents;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Animation;
  15. using System.Windows.Media.Imaging;
  16. using System.Windows.Navigation;
  17. using System.Windows.Shapes;
  18. namespace BPASmartClient.CustomResource.UserControls
  19. {
  20. /// <summary>
  21. /// Thermometer.xaml 的交互逻辑
  22. /// </summary>
  23. public partial class Thermometer : UserControl
  24. {
  25. public Thermometer()
  26. {
  27. RightDataTransfer = (float m) => m * 1.8f + 32f;
  28. InitializeComponent();
  29. }
  30. /// <summary>
  31. /// 获取或设置数值的起始值,默认为0
  32. /// </summary>
  33. public float ValueStart
  34. {
  35. get { return (float)GetValue(ValueStartProperty); }
  36. set { SetValue(ValueStartProperty, value); }
  37. }
  38. public static readonly DependencyProperty ValueStartProperty =
  39. DependencyProperty.Register("ValueStart", typeof(float), typeof(Thermometer),
  40. new PropertyMetadata(0f, RenderUpdateByPropertyChanged));
  41. /// <summary>
  42. /// 获取或设置数值的最大值,默认为100
  43. /// </summary>
  44. public float ValueMax
  45. {
  46. get { return (float)GetValue(ValueMaxProperty); }
  47. set { SetValue(ValueMaxProperty, value); }
  48. }
  49. public static readonly DependencyProperty ValueMaxProperty =
  50. DependencyProperty.Register("ValueMax", typeof(float), typeof(Thermometer),
  51. new PropertyMetadata(100f, RenderUpdateByPropertyChanged));
  52. /// <summary>
  53. /// 获取或设置数值的当前值,应该处于最小值和最大值之间
  54. /// </summary>
  55. public float Value
  56. {
  57. get { return (float)GetValue(ValueProperty); }
  58. set { SetValue(ValueProperty, value); }
  59. }
  60. public static readonly DependencyProperty ValueProperty =
  61. DependencyProperty.Register("Value", typeof(float), typeof(Thermometer),
  62. new PropertyMetadata(0f, RenderUpdateByPropertyChanged));
  63. /// <summary>
  64. /// 获取或设置温度计的分割段数,最小为2,最大1000,默认为8
  65. /// </summary>
  66. public int SegmentCount
  67. {
  68. get { return (int)GetValue(SegmentCountProperty); }
  69. set { SetValue(SegmentCountProperty, value); }
  70. }
  71. public static readonly DependencyProperty SegmentCountProperty =
  72. DependencyProperty.Register("SegmentCount", typeof(int), typeof(Thermometer),
  73. new PropertyMetadata(8, RenderUpdateByPropertyChanged));
  74. /// <summary>
  75. /// 获取或设置温度计的颜色
  76. /// </summary>
  77. public System.Windows.Media.Color TemperatureColor
  78. {
  79. get { return (System.Windows.Media.Color)GetValue(TemperatureColorProperty); }
  80. set { SetValue(TemperatureColorProperty, value); }
  81. }
  82. public static readonly DependencyProperty TemperatureColorProperty =
  83. DependencyProperty.Register("TemperatureColor", typeof(System.Windows.Media.Color), typeof(Thermometer),
  84. new PropertyMetadata(Colors.Tomato, RenderUpdateByPropertyChanged));
  85. /// <summary>
  86. /// 获取或设置温度计的颜色
  87. /// </summary>
  88. public System.Windows.Media.Color TemperatureBackColor
  89. {
  90. get { return (System.Windows.Media.Color)GetValue(TemperatureBackColorProperty); }
  91. set { SetValue(TemperatureBackColorProperty, value); }
  92. }
  93. public static readonly DependencyProperty TemperatureBackColorProperty =
  94. DependencyProperty.Register("TemperatureBackColor", typeof(System.Windows.Media.Color), typeof(Thermometer),
  95. new PropertyMetadata(Colors.Silver, RenderUpdateByPropertyChanged));
  96. /// <summary>
  97. /// 获取或设置是否显示温度计的数值
  98. /// </summary>
  99. public bool IsRenderText
  100. {
  101. get { return (bool)GetValue(IsRenderTextProperty); }
  102. set { SetValue(IsRenderTextProperty, value); }
  103. }
  104. public static readonly DependencyProperty IsRenderTextProperty =
  105. DependencyProperty.Register("IsRenderText", typeof(bool), typeof(Thermometer),
  106. new PropertyMetadata(false, RenderUpdateByPropertyChanged));
  107. /// <summary>
  108. /// 获取或设置左侧的单位显示文本,默认是℃
  109. /// </summary>
  110. public string LeftUnitText
  111. {
  112. get { return (string)GetValue(LeftUnitTextProperty); }
  113. set { SetValue(LeftUnitTextProperty, value); }
  114. }
  115. public static readonly DependencyProperty LeftUnitTextProperty =
  116. DependencyProperty.Register("LeftUnitText", typeof(string), typeof(Thermometer),
  117. new PropertyMetadata("℃", RenderUpdateByPropertyChanged));
  118. /// <summary>
  119. /// 获取或设置右侧的单位显示文本,默认是°F
  120. /// </summary>
  121. public string RightUnitText
  122. {
  123. get { return (string)GetValue(RightUnitTextProperty); }
  124. set { SetValue(RightUnitTextProperty, value); }
  125. }
  126. public static readonly DependencyProperty RightUnitTextProperty =
  127. DependencyProperty.Register("RightUnitText", typeof(string), typeof(Thermometer),
  128. new PropertyMetadata("°F", RenderUpdateByPropertyChanged));
  129. private System.Windows.Media.Color colorCenter = Colors.WhiteSmoke;
  130. private System.Windows.Media.Color colorBorder = Colors.Silver;
  131. /// <summary>
  132. /// 获取或设置右侧轴的数值和左边的关系
  133. /// </summary>
  134. [Browsable(false)]
  135. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  136. public Func<float, float> RightDataTransfer { get; set; }
  137. /// <summary>
  138. /// 使用动画的方式来更新值
  139. /// </summary>
  140. /// <param name="value">当前的数据值信息</param>
  141. /// <param name="time">动画的时间,单位,毫秒</param>
  142. public void SetValue(float value, double time = 300.0)
  143. {
  144. SingleAnimation animation = new SingleAnimation(value, TimeSpan.FromMilliseconds(time));
  145. BeginAnimation(ValueProperty, animation);
  146. }
  147. /// <summary>
  148. /// 当属性刷新的时候,进行强制更新绘图
  149. /// </summary>
  150. /// <param name="dependency"></param>
  151. /// <param name="e"></param>
  152. public static void RenderUpdateByPropertyChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs e)
  153. {
  154. (dependency as Thermometer)?.HslThermometerUpdate();
  155. }
  156. protected override void OnRender(DrawingContext drawingContext)
  157. {
  158. base.OnRender(drawingContext);
  159. HslThermometerUpdate();
  160. }
  161. /// <summary>
  162. /// 刷新界面信息
  163. /// </summary>
  164. public void HslThermometerUpdate()
  165. {
  166. canvas1.Children.Clear();
  167. int num = (int)base.ActualWidth;
  168. int num2 = (int)base.ActualHeight;
  169. if (num < 20 || num2 < 50)
  170. {
  171. return;
  172. }
  173. float num3 = (float)num * 0.1f;
  174. float num4 = (float)num * 0.2f;
  175. float num5 = num3 + 40f;
  176. float num6 = (float)num2 - num5 - 20f - num4 * 2f;
  177. LinearGradientBrush brush = new LinearGradientBrush(new GradientStopCollection(new List<GradientStop>
  178. {
  179. new GradientStop(colorCenter, 0.0),
  180. new GradientStop(colorBorder, 0.30000001192092896),
  181. new GradientStop(colorCenter, 0.800000011920929),
  182. new GradientStop(colorBorder, 1.0)
  183. }), new System.Windows.Point(0.0, 0.0), new System.Windows.Point(1.0, 0.0));
  184. WpfUtils.FillEllipse(canvas1, (float)num / 2f - num3, num5 - num3, num3 * 2f, num3 * 2f, TemperatureBackColor);
  185. WpfUtils.FillEllipse(canvas1, (float)num / 2f - num4, num5 + num6, num4 * 2f, num4 * 2f, TemperatureBackColor);
  186. WpfUtils.FillRectangle(canvas1, (float)num / 2f - num3, num5, num3 * 2f, num6 + num4, TemperatureBackColor);
  187. for (int i = 0; i <= SegmentCount; i++)
  188. {
  189. float num7 = (float)i * (ValueMax - ValueStart) / (float)SegmentCount + ValueStart;
  190. float num8 = num6 - 10f - (num7 - ValueStart) / (ValueMax - ValueStart) * (num6 - 10f) + num5;
  191. if (i > 0)
  192. {
  193. for (int j = 1; j < 10; j++)
  194. {
  195. float num9 = (num6 - 10f) / (float)SegmentCount / 10f * (float)j;
  196. if (j == 5)
  197. {
  198. WpfUtils.DrawLine(canvas1, (float)num / 2f - num3 - (float)num * 0.14f, num8 + num9, (float)num / 2f - num3 - 4f, num8 + num9, base.Foreground, 1.0);
  199. WpfUtils.DrawLine(canvas1, (float)num / 2f + num3 + (float)num * 0.14f, num8 + num9, (float)num / 2f + num3 + 4f, num8 + num9, base.Foreground, 1.0);
  200. }
  201. else
  202. {
  203. WpfUtils.DrawLine(canvas1, (float)num / 2f - num3 - (float)num * 0.1f, num8 + num9, (float)num / 2f - num3 - 4f, num8 + num9, base.Foreground, 1.0);
  204. WpfUtils.DrawLine(canvas1, (float)num / 2f + num3 + (float)num * 0.1f, num8 + num9, (float)num / 2f + num3 + 4f, num8 + num9, base.Foreground, 1.0);
  205. }
  206. }
  207. }
  208. WpfUtils.DrawLine(canvas1, (float)num / 2f - num3 - (float)num * 0.3f, num8, (float)num / 2f - num3 - 4f, num8, base.Foreground, 1.0);
  209. WpfUtils.DrawLine(canvas1, (float)num / 2f + num3 + 4f, num8, (float)num / 2f + num3 + (float)num * 0.3f, num8, base.Foreground, 1.0);
  210. WpfUtils.DrawString(canvas1, RightUnitText, base.Foreground, new RectangleF(5f, 0f, num - 10, num5 - num3), HorizontalAlignment.Right, VerticalAlignment.Center);
  211. WpfUtils.DrawString(canvas1, num7.ToString(), base.Foreground, new RectangleF(0f, num8 - 100f, (float)num / 2f - num3 - (float)num * 0.13f, 100f), HorizontalAlignment.Right, VerticalAlignment.Bottom);
  212. WpfUtils.DrawString(canvas1, LeftUnitText, base.Foreground, new RectangleF(5f, 0f, num - 10, num5 - num3), HorizontalAlignment.Left, VerticalAlignment.Center);
  213. if (RightDataTransfer != null)
  214. {
  215. WpfUtils.DrawString(canvas1, Math.Round(RightDataTransfer(num7)).ToString(), base.Foreground, new RectangleF((float)num / 2f + num3 + (float)num * 0.1f + 5f, num8 - 100f, (float)num * 0.4f, 100f), HorizontalAlignment.Left, VerticalAlignment.Bottom);
  216. }
  217. }
  218. WpfUtils.FillEllipse(canvas1, (float)num / 2f - num3 * 0.7f, num5 - num3 * 0.7f, num3 * 1.4f, num3 * 1.4f, brush);
  219. WpfUtils.FillRectangle(canvas1, (float)num / 2f - num3 * 0.7f, num5, num3 * 1.4f, num6 + num4, brush);
  220. brush = new LinearGradientBrush();
  221. brush.GradientStops = new GradientStopCollection(new List<GradientStop>
  222. {
  223. new GradientStop(TemperatureColor, 0.0),
  224. new GradientStop(TemperatureColor, 0.30000001192092896),
  225. new GradientStop(colorCenter, 0.800000011920929),
  226. new GradientStop(TemperatureColor, 1.0)
  227. });
  228. brush.StartPoint = new System.Windows.Point(0.0, 0.0);
  229. brush.EndPoint = new System.Windows.Point(1.0, 0.0);
  230. float num10 = num6 - 10f - (Value - ValueStart) / (ValueMax - ValueStart) * (num6 - 10f) + num5;
  231. if (num10 < num5 - 5f)
  232. {
  233. num10 = num5 - 5f;
  234. }
  235. if (num10 > num5 + num6 + 5f)
  236. {
  237. num10 = num5 + num6 + 5f;
  238. }
  239. WpfUtils.FillRectangle(canvas1, (float)num / 2f - num3 * 0.7f, num10, num3 * 1.4f, num6 + num4 + num5 - num10, brush);
  240. WpfUtils.FillEllipse(canvas1, (float)num / 2f - num3 * 0.7f, num10 - 1f, num3 * 1.4f, 3.0, TemperatureColor);
  241. RectangleF rectangle = new RectangleF((float)num / 2f - num4 * 0.85f, num5 + num6 + num4 * 0.15f, num4 * 1.7f, num4 * 1.7f);
  242. RadialGradientBrush radialGradientBrush = new RadialGradientBrush(colorCenter, TemperatureColor);
  243. radialGradientBrush.RadiusX = 0.5;
  244. radialGradientBrush.RadiusY = 0.5;
  245. radialGradientBrush.GradientOrigin = new System.Windows.Point(0.7, 0.3);
  246. WpfUtils.FillEllipse(canvas1, rectangle, radialGradientBrush);
  247. if (IsRenderText)
  248. {
  249. WpfUtils.DrawString(canvas1, Value.ToString(), base.Foreground, (float)num / 2f - num4, num5 + num6, num4 * 2f, num4 * 2f, HorizontalAlignment.Center, VerticalAlignment.Center);
  250. }
  251. }
  252. }
  253. }