diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslBottle.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslBottle.cs
new file mode 100644
index 0000000..01b2a4c
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslBottle.cs
@@ -0,0 +1,345 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ /// 一个类似瓶子的控件对象模型
+ [Description("一个类似瓶子,罐子的控件,支持液位显示,支持设置渐变的颜色及文本标题")]
+ public class HslBottle : UserControl
+ {
+ private Color foreColorTop = Color.FromArgb(243, 245, 139);
+ private Color foreColorEdge = Color.FromArgb(194, 190, 77);
+ private Color foreColorCenter = Color.FromArgb(226, 221, 98);
+ private Color backColorTop = Color.FromArgb(151, 232, 244);
+ private Color backColorEdge = Color.FromArgb(142, 196, 216);
+ private Color backColorCenter = Color.FromArgb(240, 240, 240);
+ private double value = 50.0;
+ private bool isOpen = false;
+ private string bottleTag = "";
+ private StringFormat sf;
+ private string headTag = "原料1";
+ private float dockHeight = 30f;
+ /// 必需的设计器变量。
+ private IContainer components = (IContainer)null;
+
+ /// 实例化一个新的控件对象
+ public HslBottle()
+ {
+ this.InitializeComponent();
+ this.sf = new StringFormat();
+ this.sf.Alignment = StringAlignment.Center;
+ this.sf.LineAlignment = StringAlignment.Center;
+ this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
+ this.SetStyle(ControlStyles.ResizeRedraw, true);
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ }
+
+ /// 获取或设置控件的背景色
+ [Browsable(true)]
+ [Description("获取或设置控件的背景色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "Transparent")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public override Color BackColor
+ {
+ get => base.BackColor;
+ set => base.BackColor = value;
+ }
+
+ /// 获取或设置瓶子的液位值。
+ [Browsable(true)]
+ [Description("获取或设置瓶子的液位值。")]
+ [DefaultValue(typeof(double), "60")]
+ [Category("HslControls")]
+ public virtual double Value
+ {
+ get => this.value;
+ set
+ {
+ if (value < 0.0 || value > 100.0)
+ return;
+ this.value = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置瓶子是否处于打开的状态。
+ [Browsable(true)]
+ [Description("获取或设置瓶子是否处于打开的状态。")]
+ [DefaultValue(typeof(bool), "false")]
+ [Category("HslControls")]
+ public virtual bool IsOpen
+ {
+ get => this.isOpen;
+ set
+ {
+ this.isOpen = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置瓶子的标签信息,用于绘制在瓶子上的信息。
+ [Browsable(true)]
+ [Description("获取或设置瓶子的标签信息,用于绘制在瓶子上的信息。")]
+ [DefaultValue(typeof(string), "")]
+ [Category("HslControls")]
+ public virtual string BottleTag
+ {
+ get => this.bottleTag;
+ set
+ {
+ this.bottleTag = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置瓶子的备注信息,用于绘制在瓶子顶部的信息。
+ [Browsable(true)]
+ [Description("获取或设置瓶子的备注信息,用于绘制在瓶子顶部的信息。")]
+ [DefaultValue(typeof(string), "原料1")]
+ [Category("HslControls")]
+ public virtual string HeadTag
+ {
+ get => this.headTag;
+ set
+ {
+ this.headTag = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置控件底座的高度
+ [Browsable(true)]
+ [DefaultValue(30f)]
+ [Description("获取或设置控件底座的高度")]
+ [Category("HslControls")]
+ public virtual float DockHeight
+ {
+ get => this.dockHeight;
+ set
+ {
+ this.dockHeight = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置前景色的边缘颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[194, 190, 77]")]
+ [Description("获取或设置前景色的边缘颜色内容")]
+ [Category("HslControls")]
+ public virtual Color ForeColorEdge
+ {
+ get => this.foreColorEdge;
+ set
+ {
+ this.foreColorEdge = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置前景色的中心颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[226, 221, 98]")]
+ [Description("获取或设置前景色的中心颜色内容")]
+ [Category("HslControls")]
+ public virtual Color ForeColorCenter
+ {
+ get => this.foreColorCenter;
+ set
+ {
+ this.foreColorCenter = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置前景色的顶部颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[243, 245, 139]")]
+ [Description("获取或设置前景色的顶部颜色内容")]
+ [Category("HslControls")]
+ public virtual Color ForeColorTop
+ {
+ get => this.foreColorTop;
+ set
+ {
+ this.foreColorTop = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置背景色的边缘颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[142, 196, 216]")]
+ [Description("获取或设置背景色的边缘颜色内容")]
+ [Category("HslControls")]
+ public virtual Color BackColorEdge
+ {
+ get => this.backColorEdge;
+ set
+ {
+ this.backColorEdge = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置背景色的中心颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[240, 240, 240]")]
+ [Description("获取或设置背景色的中心颜色内容")]
+ [Category("HslControls")]
+ public virtual Color BackColorCenter
+ {
+ get => this.backColorCenter;
+ set
+ {
+ this.backColorCenter = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置背景色的顶部颜色内容
+ [Browsable(true)]
+ [DefaultValue(typeof(Color), "[151, 232, 244]")]
+ [Description("获取或设置背景色的顶部颜色内容")]
+ [Category("HslControls")]
+ public virtual Color BackColorTop
+ {
+ get => this.backColorTop;
+ set
+ {
+ this.backColorTop = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 重绘控件的外观
+ /// 事件
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ Graphics graphics = e.Graphics;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ this.PaintHslControls(graphics, this.Width, this.Height);
+ base.OnPaint(e);
+ }
+
+ ///
+ public void PaintHslControls(Graphics g, int width, int height)
+ {
+ if (width < 15 || this.Height < 15)
+ return;
+ int num1 = (double)this.dockHeight < 1.0 ? (int)((double)this.dockHeight * (double)height) : (int)this.dockHeight;
+ int y1 = 20;
+ float x = (float)width / 2f;
+ float y2 = (float)(height - num1) - (float)((double)(height - num1 - y1) * (double)Convert.ToSingle(this.value) / 100.0);
+ int num2 = width / 50 + 3;
+ if (string.IsNullOrEmpty(this.headTag))
+ y1 = num2;
+ GraphicsPath path = new GraphicsPath();
+ path.AddPolygon(new PointF[6]
+ {
+ new PointF(0.0f, (float) y1),
+ new PointF(0.0f, (float) (height - num1)),
+ new PointF(x, (float) (height - 1)),
+ new PointF((float) (width - 1), (float) (height - num1)),
+ new PointF((float) (width - 1), (float) y1),
+ new PointF(0.0f, (float) y1)
+ });
+ LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, y1), new Point(width - 1, y1), Color.FromArgb(142, 196, 216), Color.FromArgb(240, 240, 240));
+ ColorBlend colorBlend = new ColorBlend();
+ colorBlend.Positions = new float[3] { 0.0f, 0.5f, 1f };
+ colorBlend.Colors = new Color[3]
+ {
+ this.backColorEdge,
+ this.backColorCenter,
+ this.backColorEdge
+ };
+ linearGradientBrush.InterpolationColors = colorBlend;
+ g.FillPath((Brush)linearGradientBrush, path);
+ using (Brush brush = (Brush)new SolidBrush(this.backColorTop))
+ g.FillEllipse(brush, 1, y1 - num2, width - 2, num2 * 2);
+ path.Reset();
+ path.AddPolygon(new PointF[6]
+ {
+ new PointF(0.0f, y2),
+ new PointF(0.0f, (float) (height - num1)),
+ new PointF(x, (float) (height - 1)),
+ new PointF((float) (width - 1), (float) (height - num1)),
+ new PointF((float) (width - 1), y2),
+ new PointF(0.0f, y2)
+ });
+ colorBlend.Colors = new Color[3]
+ {
+ this.foreColorEdge,
+ this.foreColorCenter,
+ this.foreColorEdge
+ };
+ linearGradientBrush.InterpolationColors = colorBlend;
+ g.FillPath((Brush)linearGradientBrush, path);
+ linearGradientBrush.Dispose();
+ using (Brush brush = (Brush)new SolidBrush(this.foreColorTop))
+ g.FillEllipse(brush, 1f, y2 - (float)num2, (float)(width - 2), (float)(num2 * 2));
+ path.Reset();
+ path.AddPolygon(new PointF[3]
+ {
+ new PointF(0.0f, (float) (height - num1)),
+ new PointF(x, (float) (height - 1)),
+ new PointF((float) (width - 1), (float) (height - num1))
+ });
+ path.AddArc(0, height - num1 - num2, width, num2 * 2, 0.0f, 180f);
+ using (Brush brush = (Brush)new SolidBrush(this.foreColorEdge))
+ g.FillPath(brush, path);
+ path.Reset();
+ path.AddLines(new PointF[4]
+ {
+ new PointF((float) width / 4f, (float) (height - num1 / 2)),
+ new PointF((float) width / 4f, (float) (height - 1)),
+ new PointF((float) ((double) width * 3.0 / 4.0), (float) (height - 1)),
+ new PointF((float) ((double) width * 3.0 / 4.0), (float) (height - num1 / 2))
+ });
+ path.AddArc((float)width / 4f, (float)(height - num1 / 2 - num2 - 1), (float)width / 2f, (float)(num2 * 2), 0.0f, 180f);
+ g.FillPath(Brushes.DimGray, path);
+ using (Brush brush = (Brush)new SolidBrush(this.ForeColor))
+ {
+ if (!string.IsNullOrEmpty(this.bottleTag))
+ g.DrawString(this.bottleTag, this.Font, brush, (RectangleF)new Rectangle(-10, 26, width + 20, 20), this.sf);
+ if (!string.IsNullOrEmpty(this.headTag))
+ g.DrawString(this.headTag, this.Font, brush, (RectangleF)new Rectangle(-10, 0, width + 20, 20), this.sf);
+ }
+ path.Dispose();
+ }
+
+ /// 清理所有正在使用的资源。
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && this.components != null)
+ this.components.Dispose();
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ this.AutoScaleMode = AutoScaleMode.None;
+ this.BackColor = Color.Transparent;
+ this.Name = nameof(HslBottle);
+ this.ResumeLayout(false);
+ }
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyer.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyer.cs
new file mode 100644
index 0000000..bc526df
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyer.cs
@@ -0,0 +1,299 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ /// 一个传送带的控件
+ [Description("传送带控件,支持正反方向设置,支持转速设置,颜色设置")]
+ public class HslConveyer : UserControl
+ {
+ private StringFormat sf = (StringFormat)null;
+ private float moveSpeed = 0.3f;
+ private float startAngle = 0.0f;
+ private float startOffect = 0.0f;
+ private Timer timer = (Timer)null;
+ private bool isConveyerActive = false;
+ private float circularRadius = 20f;
+ private HslConveyerStyle conveyerStyle = HslConveyerStyle.Horizontal;
+ /// 必需的设计器变量。
+ private IContainer components = (IContainer)null;
+
+ /// 实例化一个传送带的控件对象
+ public HslConveyer()
+ {
+ this.InitializeComponent();
+ this.sf = new StringFormat();
+ this.sf.Alignment = StringAlignment.Center;
+ this.sf.LineAlignment = StringAlignment.Center;
+ this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
+ this.SetStyle(ControlStyles.ResizeRedraw, true);
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ base.ForeColor = Color.FromArgb(142, 196, 216);
+ this.timer = new Timer();
+ this.timer.Interval = 50;
+ this.timer.Tick += new EventHandler(this.Timer_Tick);
+ this.timer.Start();
+ }
+
+ /// 获取或设置控件的背景色
+ [Browsable(true)]
+ [Description("获取或设置控件的背景色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "Transparent")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public override Color BackColor
+ {
+ get => base.BackColor;
+ set => base.BackColor = value;
+ }
+
+ /// 获取或设置当前控件的文本
+ [Browsable(true)]
+ [Description("获取或设置当前控件的文本")]
+ [Category("HslControls")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ [Bindable(true)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public override string Text
+ {
+ get => base.Text;
+ set
+ {
+ base.Text = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置控件的背景色
+ [Browsable(true)]
+ [Description("获取或设置控件的前景色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "[142, 196, 216]")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public override Color ForeColor
+ {
+ get => base.ForeColor;
+ set
+ {
+ base.ForeColor = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置传送带流动的速度,0为静止,正数为正向流动,负数为反向流动,一般情况值范围为 -9 ~ 9
+ [Browsable(true)]
+ [Description("获取或设置传送带流动的速度,0为静止,正数为正向流动,负数为反向流动,一般情况值范围为 -9 ~ 9")]
+ [Category("HslControls")]
+ [DefaultValue(0.3f)]
+ public virtual float MoveSpeed
+ {
+ get => this.moveSpeed;
+ set
+ {
+ this.moveSpeed = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道线是否激活液体显示
+ [Browsable(true)]
+ [Description("获取或设置管道线是否激活液体显示")]
+ [Category("HslControls")]
+ [DefaultValue(false)]
+ public virtual bool ConveyerActive
+ {
+ get => this.isConveyerActive;
+ set
+ {
+ this.isConveyerActive = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置两侧的圆圈的半径,当且仅当ConveyerStyle属性不为Horizontal枚举时成立
+ [Browsable(true)]
+ [Description("获取或设置两侧的圆圈的半径,当且仅当ConveyerStyle属性不为Horizontal枚举时成立")]
+ [Category("HslControls")]
+ [DefaultValue(HslConveyerStyle.Horizontal)]
+ public virtual float CircularRadius
+ {
+ get => this.circularRadius;
+ set
+ {
+ if ((double)value > (double)(this.Width / 2) || (double)value > (double)(this.Height / 2))
+ return;
+ this.circularRadius = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置传送带的样式,水平,还是上坡,还是下坡
+ [Browsable(true)]
+ [Description("获取或设置传送带的样式,水平,还是上坡,还是下坡")]
+ [Category("HslControls")]
+ [DefaultValue(HslConveyerStyle.Horizontal)]
+ public virtual HslConveyerStyle ConveyerStyle
+ {
+ get => this.conveyerStyle;
+ set
+ {
+ this.conveyerStyle = value;
+ this.Invalidate();
+ }
+ }
+
+ private void Timer_Tick(object sender, EventArgs e)
+ {
+ if ((double)this.moveSpeed == 0.0)
+ return;
+ if (this.isConveyerActive)
+ {
+ this.startOffect -= this.moveSpeed;
+ if ((double)this.startOffect <= -10.0 || (double)this.startOffect >= 10.0)
+ this.startOffect = 0.0f;
+ }
+ this.startAngle += (float)((double)this.moveSpeed * 180.0 / Math.PI / 10.0);
+ while ((double)this.startAngle < -360.0)
+ this.startAngle += 360f;
+ while ((double)this.startAngle >= 360.0)
+ this.startAngle -= 360f;
+ this.Invalidate();
+ }
+
+ /// 重绘控件的界面信息
+ /// 事件
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+ e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ this.PaintHslControls(e.Graphics, this.Width, this.Height);
+ base.OnPaint(e);
+ }
+
+ ///
+ public void PaintHslControls(Graphics g, int width, int height)
+ {
+
+ int margin = 5;
+ int offect = 5;
+ if (this.conveyerStyle == HslConveyerStyle.Horizontal)
+ this.PaintMain(g, (float)width, (float)height, (float)margin, (float)offect);
+ else if (this.conveyerStyle == HslConveyerStyle.Upslope)
+ {
+ PointF pointF1 = new PointF((float)(margin + offect) + this.circularRadius, (float)(height - 1 - margin - offect) - this.circularRadius);
+ PointF pointF2 = new PointF((float)(width - margin - offect - 1) - this.circularRadius, (float)(margin + offect) + this.circularRadius);
+ float num1 = (float)Math.Sqrt(Math.Pow((double)pointF2.Y - (double)pointF1.Y, 2.0) + Math.Pow((double)pointF2.X - (double)pointF1.X, 2.0));
+ float num2 = (float)(Math.Acos(((double)pointF2.X - (double)pointF1.X) / (double)num1) * 180.0 / Math.PI);
+ g.TranslateTransform(pointF1.X, pointF1.Y);
+ g.RotateTransform(-num2);
+ g.TranslateTransform((float)(-margin - offect) - this.circularRadius, (float)(-margin - offect) - this.circularRadius);
+ this.PaintMain(g, (float)((double)num1 + (double)(2 * margin) + (double)(2 * offect) + 2.0 * (double)this.circularRadius), (float)(2 * margin + 2 * offect) + 2f * this.circularRadius, (float)margin, (float)offect);
+ g.ResetTransform();
+ }
+ else
+ {
+ PointF pointF3 = new PointF((float)(margin + offect) + this.circularRadius, (float)(margin + offect) + this.circularRadius);
+ PointF pointF4 = new PointF((float)(width - margin - offect - 1) - this.circularRadius, (float)(height - 1 - margin - offect) - this.circularRadius);
+ float num = (float)Math.Sqrt(Math.Pow((double)pointF4.Y - (double)pointF3.Y, 2.0) + Math.Pow((double)pointF4.X - (double)pointF3.X, 2.0));
+ float angle = (float)(Math.Acos(((double)pointF4.X - (double)pointF3.X) / (double)num) * 180.0 / Math.PI);
+ g.TranslateTransform(pointF3.X, pointF3.Y);
+ g.RotateTransform(angle);
+ g.TranslateTransform((float)(-margin - offect) - this.circularRadius, (float)(-margin - offect) - this.circularRadius);
+ this.PaintMain(g, (float)((double)num + (double)(2 * margin) + (double)(2 * offect) + 2.0 * (double)this.circularRadius), (float)(2 * margin + 2 * offect) + 2f * this.circularRadius, (float)margin, (float)offect);
+ g.ResetTransform();
+ }
+ }
+
+ private void PaintMain(Graphics g, float width, float height, float margin, float offect)
+ {
+ float num1 = (float)(((double)height - (double)margin * 2.0 - (double)offect * 2.0) / 2.0);
+ float startAngle = this.startAngle;
+ Pen pen1 = new Pen(this.ForeColor, 1f);
+ Pen pen2 = new Pen(this.ForeColor, (double)num1 > 100.0 ? 7f : ((double)num1 > 20.0 ? 5f : ((double)num1 > 5.0 ? 3f : 1f)));
+ pen2.StartCap = LineCap.Round;
+ pen2.EndCap = LineCap.Round;
+ Brush brush = (Brush)new SolidBrush(this.ForeColor);
+ GraphicsPath path = new GraphicsPath();
+ path.AddArc(margin, margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), 90f, 180f);
+ path.AddLine(margin + offect + num1, margin, (float)((double)width - (double)margin - (double)offect - (double)num1 - 1.0), margin);
+ path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0), margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), -90f, 180f);
+ path.CloseFigure();
+ g.DrawPath(pen1, path);
+ g.DrawEllipse(pen1, margin + offect, margin + offect, num1 * 2f, num1 * 2f);
+ g.DrawEllipse(pen1, (float)((double)width - (double)margin - (double)num1 * 2.0) - offect, margin + offect, num1 * 2f, num1 * 2f);
+ float num2 = (float)Math.Sqrt(2.0 * (double)offect * (double)num1 + (double)offect * (double)offect);
+ float num3 = (float)(Math.Asin((double)num1 / ((double)num1 + (double)offect)) * 180.0 / Math.PI);
+ path.Reset();
+ path.AddArc(margin, margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), -num3, num3 * 2f);
+ path.AddLine(margin + offect + num1 + num2, height - margin - offect, (float)((double)width - (double)margin - (double)offect - (double)num1 - 1.0) - num2, height - margin - offect);
+ path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0), margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), 180f - num3, num3 * 2f);
+ path.CloseFigure();
+ g.DrawPath(pen1, path);
+ g.TranslateTransform(margin + offect + num1, margin + offect + num1);
+ g.RotateTransform(startAngle);
+ g.DrawLine(pen2, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f, 0.0f);
+ g.DrawLine(pen2, 0.0f, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f);
+ g.RotateTransform(-startAngle);
+ g.TranslateTransform(-margin - offect - num1, -margin - offect - num1);
+ g.TranslateTransform(width - margin - num1 - offect, margin + offect + num1);
+ g.RotateTransform(startAngle);
+ g.DrawLine(pen2, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f, 0.0f);
+ g.DrawLine(pen2, 0.0f, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f);
+ g.RotateTransform(-startAngle);
+ g.TranslateTransform(-width + margin + num1 + offect, -margin - offect - num1);
+ if (this.isConveyerActive)
+ {
+ using (Pen pen3 = new Pen(this.ForeColor, 5f))
+ {
+ pen3.DashStyle = DashStyle.Custom;
+ pen3.DashPattern = new float[2] { 5f, 5f };
+ pen3.DashOffset = this.startOffect;
+ path.Reset();
+ path.AddArc(margin + offect / 2f, margin + offect / 2f, num1 * 2f + offect, num1 * 2f + offect, 90f, 180f);
+ path.AddLine((float)((double)margin + (double)offect + (double)num1 + 1.0), margin + offect / 2f, (float)((double)width - (double)margin - (double)offect - (double)num1 - 2.0), margin + offect / 2f);
+ path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0 + (double)offect / 2.0), margin + offect / 2f, num1 * 2f + offect, num1 * 2f + offect, -90f, 180f);
+ path.CloseFigure();
+ g.DrawPath(pen3, path);
+ }
+ }
+ g.DrawString(this.Text, this.Font, brush, new RectangleF(0.0f, 0.0f, width, height), this.sf);
+ path.Dispose();
+ pen1.Dispose();
+ pen2.Dispose();
+ brush.Dispose();
+ }
+
+ /// 清理所有正在使用的资源。
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && this.components != null)
+ this.components.Dispose();
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ this.AutoScaleMode = AutoScaleMode.None;
+ this.BackColor = Color.Transparent;
+ this.Name = nameof(HslConveyer);
+ this.Size = new Size(461, 61);
+ this.ResumeLayout(false);
+ }
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyerStyle.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyerStyle.cs
new file mode 100644
index 0000000..dde0f90
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslConveyerStyle.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ /// 皮带链的样式,选择水平还是下坡,还是上坡
+ public enum HslConveyerStyle
+ {
+ /// 水平
+ Horizontal = 1,
+ /// 下坡
+ Downslope = 2,
+ /// 上坡
+ Upslope = 3,
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslDirectionStyle.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslDirectionStyle.cs
new file mode 100644
index 0000000..894eba2
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslDirectionStyle.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ public enum HslDirectionStyle
+ {
+ /// 控件是横向摆放的
+ Horizontal = 1,
+ /// 控件是纵向摆放的
+ Vertical = 2,
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLine.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLine.cs
new file mode 100644
index 0000000..8d23948
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLine.cs
@@ -0,0 +1,508 @@
+using System;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Windows.Forms;
+using System.Windows.Forms;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ /// 一个简单的管道线控件,只能横竖两种模式,支持流动动画显示
+ [Description("管道流动控件,支持横竖模式,支持显示流动动画,多个控件组合使用出更高级的效果")]
+ public class HslPipeLine : UserControl
+ {
+ private HslDirectionStyle hslPipeLineStyle = HslDirectionStyle.Horizontal;
+ private Color centerColor = Color.LightGray;
+ private Color edgeColor = Color.DimGray;
+ private Pen edgePen = new Pen(Color.DimGray, 1f);
+ private HslPipeTurnDirection hslPipeTurnLeft = HslPipeTurnDirection.None;
+ private HslPipeTurnDirection hslPipeTurnRight = HslPipeTurnDirection.None;
+ private bool isPipeLineActive = false;
+ private int pipeLineWidth = 3;
+ private Color colorPipeLineCenter = Color.DodgerBlue;
+ private float moveSpeed = 0.0f;
+ private float startOffect = 0.0f;
+ private Timer timer = (Timer)null;
+ private float antLength = 5f;
+ /// 必需的设计器变量。
+ private IContainer components = (IContainer)null;
+
+ /// 实例化一个默认的管道线对象
+ public HslPipeLine()
+ {
+ this.InitializeComponent();
+ this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ this.timer = new Timer();
+ this.timer.Interval = 50;
+ this.timer.Tick += new EventHandler(this.Timer_Tick);
+ this.timer.Start();
+ }
+
+ ///
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+ this.SizeChanged += new EventHandler(this.HslPipeLine_SizeChanged);
+ this.BackgroundImage = (Image)this.getBackgroundImg(this.Width, this.Height);
+ }
+
+ private void HslPipeLine_SizeChanged(object sender, EventArgs e)
+ {
+ this.BackgroundImage?.Dispose();
+ this.BackgroundImage = (Image)this.getBackgroundImg(this.Width, this.Height);
+ }
+
+ ///
+ protected override void OnPaint(PaintEventArgs e)
+ {
+
+ e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+ e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ this.PaintHslControls(e.Graphics, this.Width, this.Height);
+ base.OnPaint(e);
+ }
+
+ ///
+ public void PaintHslControls(Graphics g, int width, int height)
+ {
+
+ this.PaintMain(g, this.Width, this.Height);
+ }
+
+ private Bitmap getBackgroundImg(int width, int height)
+ {
+ Bitmap backgroundImg = new Bitmap(width, height);
+ Graphics g = Graphics.FromImage((Image)backgroundImg);
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ ColorBlend colorBlend = new ColorBlend();
+ colorBlend.Positions = new float[3] { 0.0f, 0.5f, 1f };
+ colorBlend.Colors = new Color[3]
+ {
+ this.edgeColor,
+ this.centerColor,
+ this.edgeColor
+ };
+ if (this.hslPipeLineStyle == HslDirectionStyle.Horizontal)
+ {
+ LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height - 1), this.edgeColor, this.centerColor);
+ linearGradientBrush.InterpolationColors = colorBlend;
+ if (this.hslPipeTurnLeft == HslPipeTurnDirection.Up)
+ this.PaintEllipse(g, colorBlend, new Rectangle(0, -this.Height - 1, 2 * this.Height, 2 * this.Height), 90f, 90f);
+ else if (this.hslPipeTurnLeft == HslPipeTurnDirection.Down)
+ this.PaintEllipse(g, colorBlend, new Rectangle(0, 0, 2 * this.Height, 2 * this.Height), 180f, 90f);
+ else
+ this.PaintRectangleBorderUpDown(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(0, 0, this.Height, this.Height));
+ if (this.hslPipeTurnRight == HslPipeTurnDirection.Up)
+ this.PaintEllipse(g, colorBlend, new Rectangle(this.Width - 1 - this.Height * 2, -this.Height - 1, 2 * this.Height, 2 * this.Height), 0.0f, 90f);
+ else if (this.hslPipeTurnRight == HslPipeTurnDirection.Down)
+ this.PaintEllipse(g, colorBlend, new Rectangle(this.Width - 1 - this.Height * 2, 0, 2 * this.Height, 2 * this.Height), 270f, 90f);
+ else
+ this.PaintRectangleBorderUpDown(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(this.Width - this.Height, 0, this.Height, this.Height));
+ if (this.Width - this.Height * 2 >= 0)
+ this.PaintRectangleBorderUpDown(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(this.Height - 1, 0, this.Width - 2 * this.Height + 2, this.Height));
+ linearGradientBrush.Dispose();
+ }
+ else
+ {
+ LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(this.Width - 1, 0), this.edgeColor, this.centerColor);
+ linearGradientBrush.InterpolationColors = colorBlend;
+ if (this.hslPipeTurnLeft == HslPipeTurnDirection.Left)
+ this.PaintEllipse(g, colorBlend, new Rectangle(-this.Width - 1, 0, 2 * this.Width, 2 * this.Width), 270f, 90f);
+ else if (this.hslPipeTurnLeft == HslPipeTurnDirection.Right)
+ this.PaintEllipse(g, colorBlend, new Rectangle(0, 0, 2 * this.Width, 2 * this.Width), 180f, 90f);
+ else
+ this.PaintRectangleBorderLeftRight(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(0, 0, this.Width, this.Width));
+ if (this.hslPipeTurnRight == HslPipeTurnDirection.Left)
+ this.PaintEllipse(g, colorBlend, new Rectangle(-this.Width - 1, this.Height - this.Width * 2, 2 * this.Width, 2 * this.Width), 0.0f, 90f);
+ else if (this.hslPipeTurnRight == HslPipeTurnDirection.Right)
+ this.PaintEllipse(g, colorBlend, new Rectangle(0, this.Height - this.Width * 2, 2 * this.Width, 2 * this.Width), 90f, 90f);
+ else
+ this.PaintRectangleBorderLeftRight(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(0, this.Height - this.Width, this.Width, this.Width));
+ if (this.Height - this.Width * 2 >= 0)
+ this.PaintRectangleBorderLeftRight(g, (Brush)linearGradientBrush, this.edgePen, new Rectangle(0, this.Width - 1, this.Width, this.Height - this.Width * 2 + 2));
+ linearGradientBrush.Dispose();
+ }
+ return backgroundImg;
+ }
+
+ private void PaintMain(Graphics g, int width, int height)
+ {
+ GraphicsPath path = new GraphicsPath(FillMode.Alternate);
+ if (this.hslPipeLineStyle == HslDirectionStyle.Horizontal)
+ {
+ if (this.isPipeLineActive)
+ {
+ if (this.Width < this.Height)
+ {
+ path.AddLine(0, this.Height / 2, this.Height, this.Height / 2);
+ }
+ else
+ {
+ if (this.hslPipeTurnLeft == HslPipeTurnDirection.Up)
+ path.AddArc(new Rectangle(this.Height / 2, -this.Height / 2 - 1, this.Height, this.Height), 180f, -90f);
+ else if (this.hslPipeTurnLeft == HslPipeTurnDirection.Down)
+ path.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180f, 90f);
+ else
+ path.AddLine(0, this.Height / 2, this.Height, this.Height / 2);
+ if (this.Width - this.Height * 2 >= 0)
+ path.AddLine(this.Height, this.Height / 2, this.Width - this.Height - 1, this.Height / 2);
+ if (this.hslPipeTurnRight == HslPipeTurnDirection.Up)
+ path.AddArc(new Rectangle(this.Width - 1 - this.Height * 3 / 2, -this.Height / 2 - 1, this.Height, this.Height), 90f, -90f);
+ else if (this.hslPipeTurnRight == HslPipeTurnDirection.Down)
+ path.AddArc(new Rectangle(this.Width - 1 - this.Height * 3 / 2, this.Height / 2, this.Height, this.Height), 270f, 90f);
+ else
+ path.AddLine(this.Width - this.Height, this.Height / 2, this.Width - 1, this.Height / 2);
+ }
+ }
+ }
+ else if (this.isPipeLineActive)
+ {
+ if (this.Width > this.Height)
+ {
+ path.AddLine(0, this.Height / 2, this.Height, this.Height / 2);
+ }
+ else
+ {
+ if (this.hslPipeTurnLeft == HslPipeTurnDirection.Left)
+ path.AddArc(new Rectangle(-this.Width / 2, this.Width / 2 - 1, this.Width, this.Width), 270f, 90f);
+ else if (this.hslPipeTurnLeft == HslPipeTurnDirection.Right)
+ path.AddArc(new Rectangle(this.Width / 2, this.Width / 2 - 1, this.Width, this.Width), 270f, -90f);
+ else
+ path.AddLine(this.Width / 2, 0, this.Width / 2, this.Width);
+ if (this.Height - this.Width * 2 >= 0)
+ path.AddLine(this.Width / 2, this.Width, this.Width / 2, this.Height - this.Width - 1);
+ if (this.hslPipeTurnRight == HslPipeTurnDirection.Left)
+ path.AddArc(new Rectangle(-this.Width / 2, this.Height - 1 - this.Width * 3 / 2, this.Width, this.Width), 0.0f, 90f);
+ else if (this.hslPipeTurnRight == HslPipeTurnDirection.Right)
+ path.AddArc(new Rectangle(this.Width / 2, this.Height - 1 - this.Width * 3 / 2, this.Width, this.Width), -180f, -90f);
+ else
+ path.AddLine(this.Width / 2, this.Height - this.Width, this.Width / 2, this.Height - 1);
+ }
+ }
+ using (Pen pen = new Pen(this.colorPipeLineCenter, (float)this.pipeLineWidth))
+ {
+ pen.DashStyle = DashStyle.Custom;
+ pen.DashPattern = new float[2]
+ {
+ this.antLength,
+ this.antLength
+ };
+ pen.DashOffset = this.startOffect;
+ g.DrawPath(pen, path);
+ }
+ path.Dispose();
+ }
+
+ private void PaintEllipse(
+ Graphics g,
+ ColorBlend colorBlend,
+ Rectangle rect,
+ float startAngle,
+ float sweepAngle)
+ {
+ GraphicsPath path = new GraphicsPath();
+ path.AddEllipse(rect);
+ PathGradientBrush pathGradientBrush = new PathGradientBrush(path);
+ pathGradientBrush.CenterPoint = (PointF)new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
+ pathGradientBrush.InterpolationColors = colorBlend;
+ g.FillPie((Brush)pathGradientBrush, rect, startAngle, sweepAngle);
+ g.DrawArc(this.edgePen, rect, startAngle, sweepAngle);
+ pathGradientBrush.Dispose();
+ path.Dispose();
+ }
+
+ private void PaintRectangleBorder(
+ Graphics g,
+ Brush brush,
+ Pen pen,
+ Rectangle rectangle,
+ bool left,
+ bool right,
+ bool up,
+ bool down)
+ {
+ g.FillRectangle(brush, rectangle);
+ if (left)
+ g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height - 1);
+ if (up)
+ g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y);
+ if (right)
+ g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
+ if (!down)
+ return;
+ g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
+ }
+
+ private void PaintRectangleBorderLeftRight(
+ Graphics g,
+ Brush brush,
+ Pen pen,
+ Rectangle rectangle)
+ {
+ this.PaintRectangleBorder(g, brush, pen, rectangle, true, true, false, false);
+ }
+
+ private void PaintRectangleBorderUpDown(Graphics g, Brush brush, Pen pen, Rectangle rectangle) => this.PaintRectangleBorder(g, brush, pen, rectangle, false, false, true, true);
+
+ private void PaintRectangleBorder(Graphics g, Brush brush, Pen pen, Rectangle rectangle) => this.PaintRectangleBorder(g, brush, pen, rectangle, true, true, true, true);
+
+ private void Timer_Tick(object sender, EventArgs e)
+ {
+ if (!this.isPipeLineActive || (double)this.moveSpeed == 0.0)
+ return;
+ this.startOffect -= this.moveSpeed;
+ if ((double)this.startOffect <= -((double)this.antLength * 2.0) || (double)this.startOffect >= (double)this.antLength * 2.0)
+ this.startOffect = 0.0f;
+ this.Invalidate();
+ }
+
+ private void Timer_Tick2(object status)
+ {
+ if (!this.isPipeLineActive)
+ return;
+ this.startOffect -= this.moveSpeed;
+ if ((double)this.startOffect <= -10.0 || (double)this.startOffect >= 10.0)
+ this.startOffect = 0.0f;
+ Bitmap bitmap = new Bitmap(this.Width, this.Height);
+ Graphics g = Graphics.FromImage((Image)bitmap);
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ this.PaintMain(g, this.Width, this.Height);
+ g.Dispose();
+ if (this.InvokeRequired)
+ {
+ //this.Invoke((m =>
+ //{
+ // this.BackgroundImage?.Dispose();
+ // this.BackgroundImage = (Image)bitmap;
+ //}), (object)bitmap);
+
+
+ this.Invoke(new EventHandler(delegate (Object sd, EventArgs ag)
+ {
+ this.BackgroundImage?.Dispose();
+ this.BackgroundImage = (Image)bitmap;
+ }), (object)bitmap);
+
+
+ }
+ else
+ {
+ this.BackgroundImage?.Dispose();
+ this.BackgroundImage = (Image)bitmap;
+ }
+ }
+
+ private void Invoke(System.Action value)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// 获取或设置控件的背景色
+ [Browsable(true)]
+ [Description("获取或设置控件的背景色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "Transparent")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public override Color BackColor
+ {
+ get => base.BackColor;
+ set => base.BackColor = value;
+ }
+
+ /// 获取或设置管道控件的边缘颜色
+ [Browsable(true)]
+ [Description("获取或设置管道控件的边缘颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "DimGray")]
+ public Color EdgeColor
+ {
+ get => this.edgeColor;
+ set
+ {
+ this.edgeColor = value;
+ this.edgePen.Dispose();
+ this.edgePen = new Pen(value, 1f);
+ this.Invalidate();
+ this.HslPipeLine_SizeChanged((object)this, new EventArgs());
+ }
+ }
+
+ /// 获取或设置管道控件的中心颜色
+ [Browsable(true)]
+ [Description("获取或设置管道控件的中心颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "LightGray")]
+ public Color LineCenterColor
+ {
+ get => this.centerColor;
+ set
+ {
+ this.centerColor = value;
+ this.Invalidate();
+ this.HslPipeLine_SizeChanged((object)this, new EventArgs());
+ }
+ }
+
+ /// 获取或设置管道控件左侧或是上方的端点朝向
+ [Browsable(true)]
+ [Description("获取或设置管道控件左侧或是上方的端点朝向")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(HslPipeTurnDirection), "None")]
+ public HslPipeTurnDirection PipeTurnLeft
+ {
+ get => this.hslPipeTurnLeft;
+ set
+ {
+ this.hslPipeTurnLeft = value;
+ this.HslPipeLine_SizeChanged((object)null, (EventArgs)null);
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道控件右侧或是下方的端点朝向
+ [Browsable(true)]
+ [Description("获取或设置管道控件左侧或是上方的端点朝向")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(HslPipeTurnDirection), "None")]
+ public HslPipeTurnDirection PipeTurnRight
+ {
+ get => this.hslPipeTurnRight;
+ set
+ {
+ this.hslPipeTurnRight = value;
+ this.HslPipeLine_SizeChanged((object)null, (EventArgs)null);
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道控件是否是横向的还是纵向的
+ [Browsable(true)]
+ [Description("获取或设置管道控件是否是横向的还是纵向的")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(HslDirectionStyle), "Vertical")]
+ public HslDirectionStyle PipeLineStyle
+ {
+ get => this.hslPipeLineStyle;
+ set
+ {
+ this.hslPipeLineStyle = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道线是否激活液体显示
+ [Browsable(true)]
+ [Description("获取或设置管道线是否激活液体显示")]
+ [Category("HslControls")]
+ [DefaultValue(false)]
+ public bool PipeLineActive
+ {
+ get => this.isPipeLineActive;
+ set
+ {
+ this.isPipeLineActive = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动
+ [Browsable(true)]
+ [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
+ [Category("HslControls")]
+ [DefaultValue(0.0f)]
+ public float MoveSpeed
+ {
+ get => this.moveSpeed;
+ set
+ {
+ this.moveSpeed = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置液体控制的定时器刷新的间隔,默认是50
+ [Browsable(true)]
+ [Description("获取或设置液体控制的定时器刷新的间隔,默认是50")]
+ [Category("HslControls")]
+ [DefaultValue(50)]
+ public int TimerInterval
+ {
+ get => this.timer.Interval;
+ set => this.timer.Interval = value;
+ }
+
+ /// 获取或设置中间管道线的宽度信息,默认为3
+ [Browsable(true)]
+ [Description("获取或设置中间管道线的宽度信息,默认为3")]
+ [Category("HslControls")]
+ [DefaultValue(3)]
+ public int PipeLineWidth
+ {
+ get => this.pipeLineWidth;
+ set
+ {
+ this.pipeLineWidth = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置流动状态时管道控件的中心颜色
+ [Browsable(true)]
+ [Description("获取或设置流动状态时管道控件的中心颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "DodgerBlue")]
+ public Color ActiveLineCenterColor
+ {
+ get => this.colorPipeLineCenter;
+ set
+ {
+ this.colorPipeLineCenter = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置蚂蚁线的长度信息
+ [Browsable(true)]
+ [Description("获取或设置蚂蚁线的长度信息")]
+ [Category("HslControls")]
+ [DefaultValue(5f)]
+ public float AntLength
+ {
+ get => this.antLength;
+ set
+ {
+ this.antLength = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 清理所有正在使用的资源。
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && this.components != null)
+ this.components.Dispose();
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ this.AutoScaleMode = AutoScaleMode.None;
+ this.BackColor = Color.Transparent;
+ this.Name = nameof(HslPipeLine);
+ this.Size = new Size(335, 21);
+ this.ResumeLayout(false);
+ }
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLineThree.cs b/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLineThree.cs
new file mode 100644
index 0000000..a6a75e8
--- /dev/null
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/HslPipeLineThree.cs
@@ -0,0 +1,448 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Mesnac.Controls.ChemicalWeighing
+{
+ /// 一个简单的管道线控件,只能横竖两种模式,支持流动动画显示
+ [Description("管道流动控件,支持横竖模式,支持显示流动动画,多个控件组合使用出更高级的效果")]
+ public class HslPipeLineThree : UserControl
+ {
+ private ArrowDirection arrowDirection = ArrowDirection.Down;
+ private Color centerColor = Color.LightGray;
+ private Color edgeColor = Color.DimGray;
+ private Pen edgePen = new Pen(Color.DimGray, 1f);
+ private bool isPipeLineActive1 = false;
+ private bool isPipeLineActive2 = false;
+ private bool isPipeLineActive3 = false;
+ private int pipeLineWidth = 3;
+ private Color colorPipeLineCenter = Color.DodgerBlue;
+ private float moveSpeed1 = 0.0f;
+ private float moveSpeed2 = 0.0f;
+ private float moveSpeed3 = 0.0f;
+ private float startOffect1 = 0.0f;
+ private float startOffect2 = 0.0f;
+ private float startOffect3 = 0.0f;
+ private Timer timer = (Timer)null;
+ private int pipeWidth = 30;
+ private float antLength = 5f;
+ /// 必需的设计器变量。
+ private IContainer components = (IContainer)null;
+
+ /// 实例化一个默认的管道线对象
+ public HslPipeLineThree()
+ {
+ this.InitializeComponent();
+ this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ this.timer = new Timer();
+ this.timer.Interval = 50;
+ this.timer.Tick += new EventHandler(this.Timer_Tick);
+ this.timer.Start();
+ }
+
+ ///
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+ e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ this.PaintHslControls(e.Graphics, this.Width, this.Height);
+ base.OnPaint(e);
+ }
+
+ ///
+ public void PaintHslControls(Graphics g, int width, int height)
+ {
+
+ if (this.arrowDirection == ArrowDirection.Down)
+ this.PaintMain(g, width, height);
+ else if (this.arrowDirection == ArrowDirection.Right)
+ {
+ g.TranslateTransform(0.0f, (float)height);
+ g.RotateTransform(-90f);
+ this.PaintMain(g, height, width);
+ g.RotateTransform(90f);
+ g.TranslateTransform(0.0f, (float)-height);
+ }
+ else if (this.arrowDirection == ArrowDirection.Left)
+ {
+ g.TranslateTransform((float)width, 0.0f);
+ g.RotateTransform(90f);
+ this.PaintMain(g, height, width);
+ g.RotateTransform(-90f);
+ g.TranslateTransform((float)-width, 0.0f);
+ }
+ else
+ {
+ g.RotateTransform(-180f);
+ g.TranslateTransform((float)-width, (float)-height);
+ this.PaintMain(g, width, height);
+ g.TranslateTransform((float)width, (float)height);
+ g.RotateTransform(180f);
+ }
+ }
+
+ private void PaintMain(Graphics g, int width, int height)
+ {
+ ColorBlend colorBlend = new ColorBlend();
+ colorBlend.Positions = new float[3] { 0.0f, 0.5f, 1f };
+ colorBlend.Colors = new Color[3]
+ {
+ this.edgeColor,
+ this.centerColor,
+ this.edgeColor
+ };
+ LinearGradientBrush linearGradientBrush1 = new LinearGradientBrush(new Point(0, 0), new Point(0, this.pipeWidth - 1), this.edgeColor, this.centerColor);
+ linearGradientBrush1.InterpolationColors = colorBlend;
+ g.FillRectangle((Brush)linearGradientBrush1, new Rectangle(0, 0, width, this.pipeWidth - 1));
+ g.DrawLine(this.edgePen, 0, 0, width, 0);
+ g.DrawLine(this.edgePen, 0, this.pipeWidth - 1, width, this.pipeWidth - 1);
+ linearGradientBrush1.Dispose();
+ LinearGradientBrush linearGradientBrush2 = new LinearGradientBrush(new Point((width - this.pipeWidth) / 2, 0), new Point((width + this.pipeWidth) / 2, 0), this.edgeColor, this.centerColor);
+ linearGradientBrush2.InterpolationColors = colorBlend;
+ g.FillPolygon((Brush)linearGradientBrush2, new PointF[5]
+ {
+ new PointF((float) (width / 2), (float) (this.pipeWidth / 2)),
+ new PointF((float) ((width - this.pipeWidth) / 2), (float) this.pipeWidth),
+ new PointF((float) ((width - this.pipeWidth) / 2), (float) height),
+ new PointF((float) ((width + this.pipeWidth) / 2 - 1), (float) height),
+ new PointF((float) ((width + this.pipeWidth) / 2 - 1), (float) this.pipeWidth)
+ });
+ linearGradientBrush2.Dispose();
+ g.DrawLine(this.edgePen, (width - this.pipeWidth) / 2, this.pipeWidth, (width - this.pipeWidth) / 2, height);
+ g.DrawLine(this.edgePen, (width + this.pipeWidth) / 2 - 1, height, (width + this.pipeWidth) / 2 - 1, this.pipeWidth);
+ GraphicsPath path1 = new GraphicsPath(FillMode.Alternate);
+ GraphicsPath path2 = new GraphicsPath(FillMode.Alternate);
+ GraphicsPath path3 = new GraphicsPath(FillMode.Alternate);
+ if (this.isPipeLineActive1)
+ path1.AddLine(0, this.pipeWidth / 2, width, this.pipeWidth / 2);
+ if (this.isPipeLineActive2)
+ {
+ path2.AddLine(0, this.pipeWidth / 2, (width - this.pipeWidth) / 2, this.pipeWidth / 2);
+ path2.AddArc(new Rectangle(width / 2 - this.pipeWidth, this.pipeWidth / 2, this.pipeWidth, this.pipeWidth), 270f, 90f);
+ path2.AddLine(width / 2, this.pipeWidth, width / 2, height);
+ }
+ if (this.isPipeLineActive3)
+ {
+ path3.AddLine(width / 2, height, width / 2, this.pipeWidth);
+ path3.AddArc(new Rectangle(width / 2, this.pipeWidth / 2, this.pipeWidth, this.pipeWidth), 180f, 90f);
+ path3.AddLine((width + this.pipeWidth) / 2, this.pipeWidth / 2, width, this.pipeWidth / 2);
+ }
+ using (Pen pen = new Pen(this.colorPipeLineCenter, (float)this.pipeLineWidth))
+ {
+ pen.DashStyle = DashStyle.Custom;
+ pen.DashPattern = new float[2] { this.antLength, 5f };
+ pen.DashOffset = this.startOffect1;
+ g.DrawPath(pen, path1);
+ pen.DashOffset = this.startOffect2;
+ g.DrawPath(pen, path2);
+ pen.DashOffset = this.startOffect3;
+ g.DrawPath(pen, path3);
+ }
+ path1.Dispose();
+ path2.Dispose();
+ path3.Dispose();
+ }
+
+ private void PaintRectangleBorder(
+ Graphics g,
+ Brush brush,
+ Pen pen,
+ Rectangle rectangle,
+ bool left,
+ bool right,
+ bool up,
+ bool down)
+ {
+ g.FillRectangle(brush, rectangle);
+ if (left)
+ g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height - 1);
+ if (up)
+ g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y);
+ if (right)
+ g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
+ if (!down)
+ return;
+ g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
+ }
+
+ private void PaintRectangleBorderUpDown(Graphics g, Brush brush, Pen pen, Rectangle rectangle) => this.PaintRectangleBorder(g, brush, pen, rectangle, false, false, true, true);
+
+ private void Timer_Tick(object sender, EventArgs e)
+ {
+ if (!this.isPipeLineActive1 && !this.isPipeLineActive2 && !this.isPipeLineActive3 || (double)this.moveSpeed1 == 0.0 && (double)this.moveSpeed2 == 0.0 && (double)this.moveSpeed3 == 0.0)
+ return;
+ this.startOffect1 -= this.moveSpeed1;
+ if ((double)this.startOffect1 <= -((double)this.antLength * 2.0) || (double)this.startOffect1 >= (double)this.antLength * 2.0)
+ this.startOffect1 = 0.0f;
+ this.startOffect2 -= this.moveSpeed2;
+ if ((double)this.startOffect2 <= -((double)this.antLength * 2.0) || (double)this.startOffect2 >= (double)this.antLength * 2.0)
+ this.startOffect2 = 0.0f;
+ this.startOffect3 -= this.moveSpeed3;
+ if ((double)this.startOffect3 <= -((double)this.antLength * 2.0) || (double)this.startOffect3 >= (double)this.antLength * 2.0)
+ this.startOffect3 = 0.0f;
+ this.Invalidate();
+ }
+
+ /// 获取或设置控件的背景色
+ [Browsable(true)]
+ [Description("获取或设置控件的背景色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "Transparent")]
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public override Color BackColor
+ {
+ get => base.BackColor;
+ set => base.BackColor = value;
+ }
+
+ /// 获取或设置管道控件的边缘颜色
+ [Browsable(true)]
+ [Description("获取或设置管道控件的边缘颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "DimGray")]
+ public Color EdgeColor
+ {
+ get => this.edgeColor;
+ set
+ {
+ this.edgeColor = value;
+ this.edgePen.Dispose();
+ this.edgePen = new Pen(value, 1f);
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道控件的中心颜色
+ [Browsable(true)]
+ [Description("获取或设置管道控件的中心颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "LightGray")]
+ public Color LineCenterColor
+ {
+ get => this.centerColor;
+ set
+ {
+ this.centerColor = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道控件是否是横向的还是纵向的
+ [Browsable(true)]
+ [Description("获取或设置管道控件是否是横向的还是纵向的")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(ArrowDirection), "Down")]
+ public ArrowDirection PipeLineStyle
+ {
+ get => this.arrowDirection;
+ set
+ {
+ this.arrowDirection = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道1号线是否激活液体显示
+ [Browsable(true)]
+ [Description("获取或设置管道线是否激活液体显示")]
+ [Category("HslControls")]
+ [DefaultValue(false)]
+ public bool PipeLineActive1
+ {
+ get => this.isPipeLineActive1;
+ set
+ {
+ this.isPipeLineActive1 = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道2号线是否激活液体显示
+ [Browsable(true)]
+ [Description("获取或设置管道线是否激活液体显示")]
+ [Category("HslControls")]
+ [DefaultValue(false)]
+ public bool PipeLineActive2
+ {
+ get => this.isPipeLineActive2;
+ set
+ {
+ this.isPipeLineActive2 = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道3号线是否激活液体显示
+ [Browsable(true)]
+ [Description("获取或设置管道线是否激活液体显示")]
+ [Category("HslControls")]
+ [DefaultValue(false)]
+ public bool PipeLineActive3
+ {
+ get => this.isPipeLineActive3;
+ set
+ {
+ this.isPipeLineActive3 = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道1号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动
+ [Browsable(true)]
+ [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
+ [Category("HslControls")]
+ [DefaultValue(0.0f)]
+ public float MoveSpeed1
+ {
+ get => this.moveSpeed1;
+ set
+ {
+ this.moveSpeed1 = value;
+ this.startOffect1 = 0.0f;
+ this.startOffect2 = 0.0f;
+ this.startOffect3 = 0.0f;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道2号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动
+ [Browsable(true)]
+ [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
+ [Category("HslControls")]
+ [DefaultValue(0.0f)]
+ public float MoveSpeed2
+ {
+ get => this.moveSpeed2;
+ set
+ {
+ this.moveSpeed2 = value;
+ this.startOffect1 = 0.0f;
+ this.startOffect2 = 0.0f;
+ this.startOffect3 = 0.0f;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道3号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动
+ [Browsable(true)]
+ [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
+ [Category("HslControls")]
+ [DefaultValue(0.0f)]
+ public float MoveSpeed3
+ {
+ get => this.moveSpeed3;
+ set
+ {
+ this.moveSpeed3 = value;
+ this.startOffect1 = 0.0f;
+ this.startOffect2 = 0.0f;
+ this.startOffect3 = 0.0f;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置液体控制的定时器刷新的间隔,默认是50
+ [Browsable(true)]
+ [Description("获取或设置液体控制的定时器刷新的间隔,默认是50")]
+ [Category("HslControls")]
+ [DefaultValue(50)]
+ public int TimerInterval
+ {
+ get => this.timer.Interval;
+ set => this.timer.Interval = value;
+ }
+
+ /// 获取或设置中间管道线的宽度信息,默认为3
+ [Browsable(true)]
+ [Description("获取或设置中间管道线的宽度信息,默认为3")]
+ [Category("HslControls")]
+ [DefaultValue(3)]
+ public int PipeLineWidth
+ {
+ get => this.pipeLineWidth;
+ set
+ {
+ this.pipeLineWidth = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置流动状态时管道控件的中心颜色
+ [Browsable(true)]
+ [Description("获取或设置流动状态时管道控件的中心颜色")]
+ [Category("HslControls")]
+ [DefaultValue(typeof(Color), "DodgerBlue")]
+ public Color ActiveLineCenterColor
+ {
+ get => this.colorPipeLineCenter;
+ set
+ {
+ this.colorPipeLineCenter = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置管道的宽度,默认为30
+ [Browsable(true)]
+ [Description("获取或设置管道的宽度,默认为30")]
+ [Category("HslControls")]
+ [DefaultValue(30)]
+ public int PipeWidth
+ {
+ get => this.pipeWidth;
+ set
+ {
+ this.pipeWidth = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 获取或设置蚂蚁线的长度信息
+ [Browsable(true)]
+ [Description("获取或设置蚂蚁线的长度信息")]
+ [Category("HslControls")]
+ [DefaultValue(5f)]
+ public float AntLength
+ {
+ get => this.antLength;
+ set
+ {
+ this.antLength = value;
+ this.Invalidate();
+ }
+ }
+
+ /// 清理所有正在使用的资源。
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && this.components != null)
+ this.components.Dispose();
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ this.AutoScaleMode = AutoScaleMode.None;
+ this.BackColor = Color.Transparent;
+ this.Name = nameof(HslPipeLineThree);
+ this.Size = new Size(135, 83);
+ this.ResumeLayout(false);
+ }
+ }
+}
diff --git a/Controls/Mesnac.Controls.ChemicalWeighing/Mesnac.Controls.ChemicalWeighing.csproj b/Controls/Mesnac.Controls.ChemicalWeighing/Mesnac.Controls.ChemicalWeighing.csproj
index ed326e8..b59a880 100644
--- a/Controls/Mesnac.Controls.ChemicalWeighing/Mesnac.Controls.ChemicalWeighing.csproj
+++ b/Controls/Mesnac.Controls.ChemicalWeighing/Mesnac.Controls.ChemicalWeighing.csproj
@@ -92,6 +92,10 @@
UserControl
+
+ UserControl
+
+
diff --git a/Main/MCEdit/Data/ComponentProperty.xml b/Main/MCEdit/Data/ComponentProperty.xml
index 552d12b..45df44a 100644
--- a/Main/MCEdit/Data/ComponentProperty.xml
+++ b/Main/MCEdit/Data/ComponentProperty.xml
@@ -1532,5 +1532,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Main/MCEdit/Data/MCProject/SCWSProject2.mprj b/Main/MCEdit/Data/MCProject/SCWSProject2.mprj
index d5423ad..3dd7702 100644
--- a/Main/MCEdit/Data/MCProject/SCWSProject2.mprj
+++ b/Main/MCEdit/Data/MCProject/SCWSProject2.mprj
@@ -23,6 +23,7 @@
+
diff --git a/Main/MCEdit/Data/MCProject/nodeForm/FormMachine.xml b/Main/MCEdit/Data/MCProject/nodeForm/FormMachine.xml
new file mode 100644
index 0000000..989bd03
--- /dev/null
+++ b/Main/MCEdit/Data/MCProject/nodeForm/FormMachine.xml
@@ -0,0 +1,206 @@
+
+
diff --git a/Main/MCEdit/Data/MCProject/nodeForm/FormMain.xml b/Main/MCEdit/Data/MCProject/nodeForm/FormMain.xml
index f211f1e..97d8471 100644
--- a/Main/MCEdit/Data/MCProject/nodeForm/FormMain.xml
+++ b/Main/MCEdit/Data/MCProject/nodeForm/FormMain.xml
@@ -1,5 +1,12 @@
+
+
+ TurnOff
+ 1196, 290
+ clfbdcf1
+ 26, 6
+
ptLeftToRight
diff --git a/Main/MCEdit/Data/MCProject/nodeForm/密炼回放.xml b/Main/MCEdit/Data/MCProject/nodeForm/密炼回放.xml
index 4bca825..f577b96 100644
--- a/Main/MCEdit/Data/MCProject/nodeForm/密炼回放.xml
+++ b/Main/MCEdit/Data/MCProject/nodeForm/密炼回放.xml
@@ -1651,7 +1651,7 @@
除尘_ValveFeed2
ptLeftToRight
ptTurnOff
-
+ OnoffValve4
134, 284
StraightTubeH24
177, 5
diff --git a/Main/MCEdit/Data/SharpDevelopControlLibrary.xml b/Main/MCEdit/Data/SharpDevelopControlLibrary.xml
index c640691..31b8110 100644
--- a/Main/MCEdit/Data/SharpDevelopControlLibrary.xml
+++ b/Main/MCEdit/Data/SharpDevelopControlLibrary.xml
@@ -117,7 +117,9 @@
-
+
+
+ //