using DevExpress.Charts.Native; using DevExpress.XtraCharts; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace IStation.WinFormUI { /// /// 图表框选辅助类 /// public class ChartBoxSelHelper { public ChartBoxSelHelper(ChartControl chart) { _chart = chart; _chart.CustomPaint += chartControl_CustomPaint; _chart.MouseDown += chartControl_MouseDown; _chart.MouseMove += chartControl_MouseMove; _chart.MouseUp += chartControl_MouseUp; } private ChartControl _chart;//图表 private bool _isStartBoxSelect = false;//是否开始框选 private Point? _startPoint;//开始点 private Rectangle? _rect;//矩形 private Color _rectBdrColor = Color.FromArgb(0, 122, 204);//矩形边框颜色 private Color _rectBgColor = Color.FromArgb(89, Color.FromArgb(0xbaa500));//矩形背景颜色 /// /// 框选完成事件 /// public event Action BoxSelCompletedEvent; /// /// 矩形边框颜色 /// public Color RectBdColor { get => _rectBdrColor; set => _rectBdrColor = value; } /// /// 矩形背景颜色 /// public Color RectBgColor { get => _rectBgColor; set => _rectBgColor = value; } //自定义绘制矩形 private void chartControl_CustomPaint(object sender, CustomPaintEventArgs e) { if (!(e is DXCustomPaintEventArgs dxArgs)) return; if (_rect != null) { dxArgs.Cache.DrawRectangle(_rect.Value, RectBdColor, 1); dxArgs.Cache.FillRectangle(RectBgColor, _rect.Value); } } //鼠标按下 private void chartControl_MouseDown(object sender, MouseEventArgs e) { if (_isStartBoxSelect) { _startPoint = e.Location; } } //鼠标移动 private void chartControl_MouseMove(object sender, MouseEventArgs e) { if (_isStartBoxSelect && _startPoint != null) { _rect = GetRectangle(_startPoint.Value, e.Location); _chart.Invalidate(); } } private Rectangle GetRectangle(Point p1, Point p2) { int x = p1.X < p2.X ? p1.X : p2.X; int y = p1.Y < p2.Y ? p1.Y : p2.Y; int width = Math.Abs(p1.X - p2.X); int height = Math.Abs(p1.Y - p2.Y); return new Rectangle(x, y, width, height); } private RectangleF GetRectangle(PointF p1, PointF p2) { float x = p1.X < p2.X ? p1.X : p2.X; float y = p1.Y < p2.Y ? p1.Y : p2.Y; float width = Math.Abs(p1.X - p2.X); float height = Math.Abs(p1.Y - p2.Y); return new RectangleF(x, y, width, height); } //鼠标弹起 private void chartControl_MouseUp(object sender, MouseEventArgs e) { _isStartBoxSelect = false; _startPoint = null; if (_rect != null) { this.BoxSelCompletedEvent?.Invoke(e); } } /// /// 开始框选 /// public void StartBoxSel() { _isStartBoxSelect = true; } /// /// 关闭框选 /// public void CloseBoxSel() { _rect = null; _chart.Invalidate(); } //计算时间选中的点 public List CalcuDataTimeSelSeriesPoints(List seriesList) { if (seriesList == null || seriesList.Count < 1) return default; if (_rect == null) return default; var chartStartPoint = _rect.Value.Location; var chartEndPoint = new Point(_rect.Value.X + _rect.Value.Width, _rect.Value.Y + _rect.Value.Height); var xyDiagram = _chart.Diagram as XYDiagram2D; var coordiStart = xyDiagram.PointToDiagram(chartStartPoint); var coordiEnd = xyDiagram.PointToDiagram(chartEndPoint); if (coordiStart.IsEmpty || coordiEnd.IsEmpty) return default; var start_time = coordiStart.DateTimeArgument; var start_value = coordiStart.NumericalValue; var end_time = coordiEnd.DateTimeArgument; var end_value = coordiEnd.NumericalValue; var list = new List(); foreach (Series series in seriesList) { foreach (SeriesPoint point in series.Points) { var dataTime = point.DateTimeArgument; if (dataTime >= start_time && dataTime <= end_time) { var dataValue=point.Values[0]; if ((dataValue >= start_value && dataValue <= end_value) || (dataValue <= start_value && dataValue >= end_value)) { list.Add(point); } } } } return list; } //计算数值选中的点 public List CalcuNumericalSelSeriesPoints (List seriesList) { if (seriesList == null || seriesList.Count < 1) return default; if (_rect == null) return default; var chartStartPoint = _rect.Value.Location; var chartEndPoint = new Point(_rect.Value.X + _rect.Value.Width, _rect.Value.Y + _rect.Value.Height); var xyDiagram = _chart.Diagram as XYDiagram2D; var coordiStart = xyDiagram.PointToDiagram(chartStartPoint); var coordiEnd = xyDiagram.PointToDiagram(chartEndPoint); if (coordiStart.IsEmpty || coordiEnd.IsEmpty) return default; PointF startPoint = new PointF((float)coordiStart.NumericalArgument, (float)coordiStart.NumericalValue); PointF endPoint = new PointF((float)coordiEnd.NumericalArgument, (float)coordiEnd.NumericalValue); var bounds = GetRectangle(startPoint, endPoint); var list = new List(); foreach (Series series in seriesList) { foreach (SeriesPoint point in series.Points) { float x = (float)point.NumericalArgument; float y = (float)point.Values[0]; if (bounds.Contains(x, y)) { list.Add(point); } } } return list; } } }