using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; using System.Data; using System.ComponentModel; using System.Drawing; using System.Windows.Forms.DataVisualization.Charting; namespace FLY.ControlLibrary { /// <summary> /// GraphScan.xaml 的交互逻辑 /// </summary> public partial class GraphScan_coslight : GraphScan { public GraphScan_coslight():base() { this.chart1.SizeChanged += new EventHandler(chart1_SizeChanged); this.PropertyChanged += new PropertyChangedEventHandler(GraphScan_coslight_PropertyChanged); } void GraphScan_coslight_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsReversed") { chart1.ChartAreas[0].AxisX.IsReversed = IsReversed; if (!IsReversed) chart1.ChartAreas[0].Position.X = 0F; else chart1.ChartAreas[0].Position.X = 100F - chart1.ChartAreas[0].Position.Width; } } /// <summary> /// 解决右边坐标显示问题 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void chart1_SizeChanged(object sender, EventArgs e) { ChartArea area = chart1.ChartAreas[0]; Graphics g = chart1.CreateGraphics(); SizeF size = g.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸 float pw = 100 * (chart1.Width - size.Width - 10) / chart1.Width; chart1.ChartAreas[0].Position.Width = (int)pw; chart1.ChartAreas[0].Position.Height = 100F; chart1.ChartAreas[0].Position.Y = 0F; if (!IsReversed) chart1.ChartAreas[0].Position.X = 0F; else chart1.ChartAreas[0].Position.X = 100F - chart1.ChartAreas[0].Position.Width; g.Dispose(); } /// <summary> /// 获取实际应用的目标值,公差 /// </summary> /// <param name="target"></param> /// <param name="alarm"></param> /// <param name="yrange"></param> /// <param name="ctrlline"></param> /// <param name="ispercent"></param> void GetActualTargetAlarm( out double target, out double alarm, out double yrange, out double ctrlline, out bool ispercent) { double multi = Multi; if (IsAutoTarget) target = AutoTarget / multi;//AutoTarget 计算得到的平均值 else target = Target / multi; ispercent = IsPercent; if ((ispercent) && (Target <= 0) || (Alarm < 0) || (target <= 0)) ispercent = false; if (ispercent) { alarm = target * Alarm / Target; } else { alarm = Alarm / multi; } yrange = alarm * YRangePercent; if ((alarm < 0.1) || (yrange < 0.3)) { alarm = 0.1; yrange = 0.3; } ctrlline = CtrlLine / multi; } /// <summary> /// 画虚线 与 右坐标 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void Chart1_PrePaint(object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e) { if (e.ChartElement is ChartArea) { ChartArea area = (ChartArea)e.ChartElement; if (Double.IsNaN(area.AxisY.Minimum)) return; double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); //画目标值 System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Green, 2); DrawYGridTick(e.ChartGraphics, pen, target); //画规格线 if (alarm < yrange) { pen.Color = System.Drawing.Color.Red; DrawYGridTick(e.ChartGraphics, pen, target + alarm); DrawYGridTick(e.ChartGraphics, pen, target - alarm); } //画控制线 if (HasCtrlLine) { if (ctrlline < yrange) { pen.Color = System.Drawing.Color.Orange; pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; pen.DashPattern = new float[] { 5, 5 }; DrawYGridTick(e.ChartGraphics, pen, target + ctrlline); pen.Color = System.Drawing.Color.Blue; DrawYGridTick(e.ChartGraphics, pen, target - ctrlline); } } //写字 //if (y > area.AxisY.Maximum || y < area.AxisY.Minimum) // return; ChartGraphics cg = e.ChartGraphics; Graphics graph = cg.Graphics; RectangleF rectangele_target = new RectangleF(); RectangleF rectangele_alarm_min = new RectangleF(); RectangleF rectangele_alarm_max = new RectangleF(); RectangleF rectangele_ctrlline_min = new RectangleF(); RectangleF rectangele_ctrlline_max = new RectangleF(); rectangele_target.Size = graph.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸 double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum); cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = 0 }); // Convert relative coordinates to absolute coordinates. rectangele_target.Location = cg.GetAbsolutePoint(new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target) }); if (!IsReversed) rectangele_target.X += 2; else rectangele_target.X -= (rectangele_target.Width + 2); rectangele_target.Y -= rectangele_target.Height / 2;//移到中间 graph.DrawString( "目标值", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Green), rectangele_target); //画控制线 if (HasCtrlLine) { if ((ctrlline < yrange) && (ctrlline < alarm)) { rectangele_ctrlline_min.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_ctrlline_min.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - ctrlline) }); if (!IsReversed) rectangele_ctrlline_min.X += 2; else rectangele_ctrlline_min.X -= (rectangele_ctrlline_min.Width + 2); rectangele_ctrlline_min.Y -= rectangele_ctrlline_min.Height / 2;//移到中间 if (rectangele_ctrlline_min.Top < rectangele_target.Bottom) { rectangele_ctrlline_min.Y = rectangele_target.Bottom; } graph.DrawString( "控制线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Blue), rectangele_ctrlline_min); rectangele_ctrlline_max.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_ctrlline_max.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + ctrlline) }); if (!IsReversed) rectangele_ctrlline_max.X += 2; else rectangele_ctrlline_max.X -= (rectangele_ctrlline_max.Width + 2); rectangele_ctrlline_max.Y -= rectangele_ctrlline_max.Height / 2;//移到中间 if (rectangele_ctrlline_max.Bottom > rectangele_target.Top) { rectangele_ctrlline_max.Y = rectangele_target.Top - rectangele_ctrlline_max.Height; } graph.DrawString( "控制线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Orange), rectangele_ctrlline_max); } } //规格线 if (alarm < yrange) { rectangele_alarm_min.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_alarm_min.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - alarm) }); if (!IsReversed) rectangele_alarm_min.X += 2; else rectangele_alarm_min.X -= (rectangele_alarm_min.Width + 2); rectangele_alarm_min.Y -= rectangele_alarm_min.Height / 2;//移到中间 if (HasCtrlLine && (ctrlline < alarm)) { if (rectangele_alarm_min.Top < rectangele_ctrlline_min.Bottom) { rectangele_alarm_min.Y = rectangele_ctrlline_min.Bottom; } } else { if (rectangele_alarm_min.Top < rectangele_target.Bottom) { rectangele_alarm_min.Y = rectangele_target.Bottom; } } graph.DrawString( "规格线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_min); rectangele_alarm_max.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_alarm_max.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + alarm) }); if (!IsReversed) rectangele_alarm_max.X += 2; else rectangele_alarm_max.X -= (rectangele_alarm_max.Width + 2); rectangele_alarm_max.Y -= rectangele_alarm_max.Height / 2;//移到中间 if (HasCtrlLine && (ctrlline < alarm)) { if (rectangele_alarm_max.Bottom > rectangele_ctrlline_max.Top) { rectangele_alarm_max.Y = rectangele_ctrlline_max.Top - rectangele_alarm_max.Height; } } else { if (rectangele_alarm_max.Bottom > rectangele_target.Top) { rectangele_alarm_max.Y = rectangele_target.Top - rectangele_alarm_max.Height; } } graph.DrawString( "规格线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_max); } } } void DrawYGridTick(ChartGraphics cg, System.Drawing.Pen pen, double y) { ChartArea area = chart1.ChartAreas[0]; if (y > area.AxisY.Maximum || y < area.AxisY.Minimum) return; // Take Graphics object from chart Graphics graph = cg.Graphics; // Convert X and Y values to screen position double py = cg.GetPositionFromAxis(area.Name, AxisName.Y, y); double XMin = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Minimum); double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum); System.Drawing.PointF[] points = new System.Drawing.PointF[2]; points[0].X = (float)XMin; points[1].X = (float)XMax; points[0].Y = points[1].Y = (float)py; // Convert relative coordinates to absolute coordinates. points[0] = cg.GetAbsolutePoint(points[0]); points[1] = cg.GetAbsolutePoint(points[1]); graph.DrawLine(pen, points[0], points[1]); } void DrawYLabel(ChartGraphics cg, System.Drawing.Brush brush, Font font, double y, string msg) { ChartArea area = chart1.ChartAreas[0]; if (y > area.AxisY.Maximum || y < area.AxisY.Minimum) return; // Take Graphics object from chart Graphics graph = cg.Graphics; // Convert X and Y values to screen position double py = cg.GetPositionFromAxis(area.Name, AxisName.Y, y); double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum); System.Drawing.PointF point = new System.Drawing.PointF(); point.X = (float)XMax; point.Y = (float)py; // Convert relative coordinates to absolute coordinates. point = cg.GetAbsolutePoint(point); graph.DrawString(msg, font, brush, point); } /// <summary> /// 与 Multi,Target,YRange,Alarm 相关 /// </summary> public override void UpdateAxisY() { double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); Axis axisY = chart1.ChartAreas["Default"].AxisY; axisY.Crossing = target; // Set manual minimum and maximum values. axisY.Minimum = target - yrange; axisY.Maximum = target + yrange; axisY.CustomLabels.Clear(); //中间目标值,肯定不以%显示 SetCustomLabel(axisY, target, GridTickTypes.All, System.Drawing.Color.Green, false, null); //上下限 SetCustomLabel(axisY, target + alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null); SetCustomLabel(axisY, target - alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null); //显示范围数值 SetCustomLabel(axisY, axisY.Minimum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null); SetCustomLabel(axisY, axisY.Maximum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null); //显示范围数值 if (yrange != 2 * alarm) { SetCustomLabel(axisY, target + alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null); SetCustomLabel(axisY, target - alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null); } //显示范围太小,多加纵坐标 if (yrange <= alarm) { SetCustomLabel(axisY, target - yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null); SetCustomLabel(axisY, target + yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null); } } protected override void UpdateOnePoint(int index) { double multi = Multi; int emptyvalue = EmptyValue; DataPoint point; if (index >= chart1.Series["Series 1"].Points.Count) { chart1.Series["Series 1"].Points.AddXY( FirstBoltNo + index, (double)DataSource[index] / multi); point = chart1.Series["Series 1"].Points[index]; } else { point = chart1.Series["Series 1"].Points[index]; point.YValues[0] = DataSource[index] / multi; point.XValue = FirstBoltNo + index; } //设定空数据 if (DataSource[index] == emptyvalue) { point.IsEmpty = true; } else { point.IsEmpty = false; } System.Drawing.Color c; double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); double data = DataSource[index] / multi; if (data > (target + yrange)) { c = System.Drawing.Color.Violet; } else if (data > (target + alarm)) { c = System.Drawing.Color.Red; } else if (data >= (target - alarm)) { if (HasCtrlLine) { if (data > (target + ctrlline)) { c = System.Drawing.Color.Orange; } else if (data >= (target - ctrlline)) { c = System.Drawing.Color.Green; } else { c = System.Drawing.Color.FromArgb(0x00,0x8B,0xE5); } } else { c = System.Drawing.Color.Green; } } else if (data >= (target - yrange)) { c = System.Drawing.Color.Red; } else { c = System.Drawing.Color.Violet; } if (ChartType == SeriesChartType.Line) { point.MarkerColor = c; point.BorderColor = chart1.Series["Series 1"].BorderColor; point.Color = chart1.Series["Series 1"].Color; } else { point.MarkerColor = c; point.BorderColor = c; point.Color = c; } } } }