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;
}
}
}