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
|
{
|
/// <summary>
|
/// 图表框选辅助类
|
/// </summary>
|
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));//矩形背景颜色
|
|
/// <summary>
|
/// 框选完成事件
|
/// </summary>
|
public event Action<MouseEventArgs> BoxSelCompletedEvent;
|
|
/// <summary>
|
/// 矩形边框颜色
|
/// </summary>
|
public Color RectBdColor { get => _rectBdrColor; set => _rectBdrColor = value; }
|
|
/// <summary>
|
/// 矩形背景颜色
|
/// </summary>
|
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);
|
}
|
}
|
|
/// <summary>
|
/// 开始框选
|
/// </summary>
|
public void StartBoxSel()
|
{
|
_isStartBoxSelect = true;
|
}
|
|
/// <summary>
|
/// 关闭框选
|
/// </summary>
|
public void CloseBoxSel()
|
{
|
_rect = null;
|
_chart.Invalidate();
|
}
|
|
//计算时间选中的点
|
public List<SeriesPoint> CalcuDataTimeSelSeriesPoints(List<Series> 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<SeriesPoint>();
|
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<SeriesPoint> CalcuNumericalSelSeriesPoints (List<Series> 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<SeriesPoint>();
|
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;
|
}
|
|
}
|
}
|