ZedGraph 可选定轴 通过鼠标移动或通过滚轮设置轴的范围
文章目录
- 前言
- 效果图
- 引用的Dll
- 确定轴的位置
- 详细代码
- 实现移动轴范围和滚轮设置轴范围
- 具体实现的代码
- 完整的代码
前言
使用的ZedGraph绘制曲线图时,轴的范围要么是根据采集到的数据自动变化,要么是在缩放平移时才能看到轴的变化。要想设置轴的范围,第一个想到的方法是,建立一个对话框,输入起始坐标,轴间隔(或坐标的最大最小值)来设置,但这样子太麻烦了。下面介绍另一个方法,可以通过鼠标滑动选中的轴,或者是在选定轴上滚动鼠标滚轮来设置轴的范围。
效果图
话不多说,先上效果图:
引用的Dll
我使用的是ZedGraph.Winfroms,勾选【包括预发行版】才能看到。
说明一下:
如果使用第1个ZedGraph的话,鼠标移动轴更改轴范围可以实现,但滚轮移动轴更改轴范围就实现不了,有调用的一个函数在ZedGraph.Winform中。
使用第二个ZedGraph.Winfroms的话,两种方式都能更改轴的范围。
确定轴的位置
这里比较难的之一就是如何确定轴的位置,我放一个图配合解说和代码,就能一清二楚的知道轴的位置应该怎么计算了。
①先看看左侧的Y轴。起始绘制点在(0,0),终点绘制点在(GraphPane.Chart.Rect.Left,0)GraphPane.Chart.Rect.Left 等于GraphPane.Chart.Rect.X。可以看到左侧Y轴都在0~GraphPane.Chart.Rect.Left 的这一段范围中。
②然后看看右侧的Y轴。起始绘制点在(GraphPane.Chart.Rect.Right,0),终点绘制点在(MasterPane.Rect.Right,0),即红色框的最右边到的绿色框的最右边.可以看到右侧Y轴都在GraphPane.Chart.Rect.Right~MasterPane.Chart.Rect.Left 的这一段范围中。
③ 最后看看X轴的位置。同理,X轴绘制的区域范围的起始绘制点在(0, GraphPane.Chart.Rect.Bottom),终点绘制点在(0, MasterPane.Chart.Rect.Bottom)
每条轴所占的宽度可以通过轴的 public float CalcSpace(Graphics g, GraphPane pane, float scaleFactor, out float fixedSpace);
计算出来,其中out float fixedSpace就是当前轴所占用的宽度。
当鼠标在这些区域按下或滚动时,就能从鼠标的位置来判断是不是要移动轴了,以及移动的是哪一个轴。
详细代码
/// <summary>/// 缩放移动轴/// </summary>/// <param name="e">鼠标事件</param>/// <param name="tempIsWheel">滚轮事件true 点击事件false</param>/// <returns>返回Y轴索引</returns>private int FindMoveAxis(MouseEventArgs e, bool tempIsWheel){this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;//Y轴索引int tmpIndexY = -1;#region 判断是否移动左侧Y轴//初始化起始坐标点float tmpStartX = 0;//其中Rect://获取或设置包含由轴(x轴、y轴和y2轴)限定的区域的矩形。//如果手动设置此值,则IsRectAuto值将自动设置为false。//X是获取矩形区域左上角的坐标float tmpEndX = Oscillograph.GraphPane.Chart.Rect.X - 5;//缩放比例float scaleFactor = Oscillograph.GraphPane.CalcScaleFactor();Graphics g = Oscillograph.CreateGraphics();//如果鼠标落下的位置在此范围内 0到 矩形区域左上角的图标//即鼠标落点在Y轴的区域if (e.X > tmpStartX && e.X < tmpEndX){//开始拖拽时Y的坐标值 = 鼠标的Y坐标this.StartPosition = e.Y;//获取Y轴的数量int yAxisCount = Oscillograph.GraphPane.YAxisList.Count;//记录使用的Y轴索引List<int> tmpList = new List<int>();for (int i = yAxisCount - 1; i >= 0; i--){//左侧区域if (!Oscillograph.GraphPane.YAxisList[i].IsVisible){//Y轴不可见yAxisCount--;}else{//记录使用的Y轴索引tmpList.Add(i);}}//就是获取Y左边Y轴的区域除以Y轴的数量 就是每个Y轴的单位宽度float unit = (tmpEndX - tmpStartX) / yAxisCount;unit = 0;//通过循环获取自己要拖拽哪个Y轴for (int i = 0; i < yAxisCount; i++){//计算刻度轴标签的最大宽度float tmpSpecae = Oscillograph.GraphPane.YAxisList[tmpList[i]].CalcSpace(g, Oscillograph.GraphPane, scaleFactor, out float tmpFloat);//如果鼠标所在的X坐标对应Y轴的区域内if (e.X < (unit + tmpSpecae) && e.X > unit){//Y轴索引tmpIndexY = tmpList[i];if (tmpIndexY >= 0){//拖拽Y轴标识改为truethis.IsDragYAxis = true;//拖拽的Y轴的索引就是反顺序的索引this.DragAxis = Oscillograph.GraphPane.YAxisList[tmpIndexY];break;}}unit += tmpSpecae;}}#endregionif (this.IsDragYAxis){//检测选择或滚动Y轴g.Dispose();return tmpIndexY;}#region 判断是否移动右侧Y轴//右侧的X要加上矩形的宽度tmpStartX = Oscillograph.GraphPane.Chart.Rect.Right;tmpEndX = Oscillograph.MasterPane.Rect.Right - 5;if (e.X > tmpStartX && e.X < tmpEndX){//开始拖拽时Y的坐标值 = 鼠标的Y坐标this.StartPosition = e.Y;//获取Y轴的数量int yAxisCount = Oscillograph.GraphPane.Y2AxisList.Count;//就是获取Y左边Y轴的区域除以Y轴的数量 就是每个Y轴的单位宽度float unit = (tmpEndX - tmpStartX) / yAxisCount;//通过循环获取自己要拖拽哪个Y轴for (int i = 0; i < yAxisCount; i++){//如果鼠标所在的X坐标对应Y轴的区域内if (e.X < tmpStartX + unit * (i + 1) && e.X > unit * i + tmpStartX){//拖拽Y轴标识改为truethis.IsDragYAxis = true;//Y轴索引tmpIndexY = i;//拖拽的Y轴的索引就是反顺序的索引this.DragAxis = Oscillograph.GraphPane.Y2AxisList[tmpIndexY];break;}}}#endregionif (this.IsDragYAxis && tmpIndexY > -1){//检测选择或滚动Y轴return (tmpIndexY + Oscillograph.GraphPane.YAxisList.Count-1);}#region 是否拖拽X轴//sender.GraphPane.Chart.Rect.Y 获取左上角的Y坐标 再加上区域高度float tmpStartY = Oscillograph.GraphPane.Chart.Rect.Bottom;float tmpS = Oscillograph.GraphPane.XAxis.CalcSpace(g, Oscillograph.GraphPane, scaleFactor, out float tmpF);float tmpEndY = tmpStartY + tmpS * 0.8f;if (e.Y > tmpStartY && e.Y < tmpEndY){//将拖拽X轴设置为truethis.IsDragXAxis = true;this.StartPosition = e.X;this.DragAxis = Oscillograph.GraphPane.XAxis;}#endregionreturn 0;}
实现移动轴范围和滚轮设置轴范围
1 选中轴并移动,根据移动的量设置轴范围。鼠标按下MouseDown
的时候判断是否要设置轴,鼠标移动MouseMove
的时候设置轴范围,鼠标松开MouseUp
的时候停止更新轴范围
2 鼠标滚轮放置在轴上,根据滚动的滚轮速度,设置轴范围。滚轮滚动MouseWheel
的时候,判断是否要设置轴范围,如果是则设置,滚动一次就设置一次。
具体实现的代码
/// <summary>/// 鼠标按下/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns>true:不会往下继续执行基类的MouseDown功能; false会往下继续执行基类的MouseDown功能</returns>private bool Oscillograph_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e){//判断鼠标按下的位置,是否在轴的位置,以及选中的是哪一个轴this.FindMoveAxis(e, false);if((this.IsDragXAxis || this.IsDragYAxis) && this.DragAxis != null){//不让基类的MouseDown事件继续往下执行return true;}return false;}/// <summary>/// 鼠标移动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns></returns>private bool Oscillograph_MouseMoveEvent(ZedGraphControl sender, MouseEventArgs e){//如果是拖动Y轴if (this.IsDragYAxis && DragAxis!=null){//速度(占的比例)float rate = (e.Y - this.StartPosition) / Oscillograph.GraphPane.Chart.Rect.Height;//距离float diff = rate * (float)(this.DragAxis.Scale.Max - this.DragAxis.Scale.Min);if (Math.Abs(rate) >= 0.01){//Y轴的刻度最大值加上距离this.DragAxis.Scale.Max += diff;//Y轴刻度的最小值加上距离this.DragAxis.Scale.Min += diff;this.StartPosition = e.Y;//刷新曲线图Oscillograph.AxisChange();Oscillograph.Refresh();}}//拖拽X轴if (this.IsDragXAxis && DragAxis != null){float rate = (e.X - this.StartPosition) / Oscillograph.GraphPane.Chart.Rect.Width;float diff = rate * (float)(this.DragAxis.Scale.Max - this.DragAxis.Scale.Min);if (Math.Abs(rate) >= 0.01){this.DragAxis.Scale.Max -= diff;this.DragAxis.Scale.Min -= diff;this.StartPosition = e.X;Oscillograph.AxisChange();Oscillograph.Refresh();}}if ((this.IsDragYAxis || this.IsDragXAxis) && DragAxis != null){return true;}return false;}/// <summary>/// 松开鼠标(释放)/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns></returns>private bool Oscillograph_MouseUpEvent(ZedGraphControl sender, MouseEventArgs e){this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;return false;}/// <summary>/// 鼠标滚轮滚动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Oscillograph_MouseWheel(object sender, MouseEventArgs e){//判断鼠标按下的位置,是否在轴的位置,以及选中的是哪一个轴int tmpIndexY = this.FindMoveAxis(e, false);if ((this.IsDragXAxis || this.IsDragYAxis) && this.DragAxis != null){//不让基类的MouseDown事件继续往下执行if (tmpIndexY == -1 || !this.DragAxis.IsVisible){//轴不可见return;}//鼠标的坐标PointF centerPoint = new PointF(e.X, e.Y);//缩放灵敏度double zoomFraction = (1 + (e.Delta < 0 ? 1.0 : -1.0)* 0.1);//刻度轴自适应this.ResetAutoScale(this.DragAxis.Scale);//缩放轴this.ZoomAxis(Oscillograph.GraphPane, zoomFraction,centerPoint, this.DragAxis, this.IsDragYAxis, tmpIndexY);this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;return;}}
完整的代码
上面的步骤介绍了整体的思路,下面贴的是Demo的全都代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
namespace ZedgraphMulY
{/// <summary>/// 移动示波器的轴/// </summary>public partial class MoveOscAxisForm : Form{private ZedGraphControl Oscillograph;private GraphPane MyPane; //示波器界面控件public MoveOscAxisForm(){InitializeComponent();this.AddCenterControls();this.RegisterOscEvent();}//中间private void AddCenterControls(){//曲线图Oscillograph = new ZedGraphControl();Oscillograph.Name = "Oscillograph";OscillographInit(); //初始化示波器//iniOscCurve(); //初始化通道数据Oscillograph.Dock = DockStyle.Fill;this.Controls.Add(Oscillograph);}#region 初始化示波器private void OscillographInit(){this.Oscillograph.BorderStyle = BorderStyle.None;MyPane = this.Oscillograph.GraphPane;MyPane.Legend.IsVisible = false;MyPane.Title.IsVisible = false;//背景色MyPane.Chart.Fill.Type = FillType.Solid;this.Oscillograph.MasterPane.Border.IsVisible = false;MyPane.Border.IsVisible = false;MyPane.Margin.Top = 22;MyPane.Margin.Right = 22;MyPane.Margin.Left = 10;MyPane.Margin.Bottom = 10;#region X轴网格线MyPane.XAxis.MajorGrid.IsVisible = true;MyPane.XAxis.MajorGrid.IsZeroLine = false;MyPane.XAxis.MajorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.XAxis.MajorGrid.DashOff = 4f;MyPane.XAxis.MajorGrid.DashOn = 4f;MyPane.XAxis.MajorGrid.PenWidth = 0.1f;MyPane.XAxis.MinorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.XAxis.MinorGrid.DashOff = 4f;MyPane.XAxis.MinorGrid.DashOn = 4f;MyPane.XAxis.MinorGrid.PenWidth = 0.1f;MyPane.XAxis.MajorTic.IsAllTics = false;MyPane.XAxis.MinorTic.IsAllTics = false;MyPane.XAxis.Scale.FontSpec.FontColor = Color.FromArgb(150, 150, 150);MyPane.XAxis.Scale.FontSpec.Size = 10;MyPane.XAxis.Scale.Max = 100;MyPane.XAxis.Scale.Min = 0;MyPane.XAxis.Scale.MajorStep = 10;MyPane.XAxis.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);MyPane.XAxis.Title.FontSpec.Size = 10;MyPane.XAxis.Title.Text = "(ms)";MyPane.XAxis.Type = AxisType.Linear;#endregion//背景颜色ChangeBackColorForm();#region 左侧第一条Y轴 Y轴网格线MyPane.YAxis.MajorGrid.IsVisible = true;MyPane.YAxis.MajorGrid.IsZeroLine = false;MyPane.YAxis.MajorGrid.PenWidth = 0.1f;MyPane.YAxis.MajorGrid.DashOn = 4f;MyPane.YAxis.MajorGrid.DashOff = 4f;MyPane.YAxis.MajorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.YAxis.MinorGrid.IsVisible = false;MyPane.YAxis.MajorTic.Color = Color.FromArgb(150, 150, 150);MyPane.YAxis.MajorTic.IsAllTics = false;MyPane.YAxis.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度MyPane.YAxis.MinorTic.IsAllTics = false;MyPane.YAxis.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度MyPane.YAxis.Scale.MaxAuto = false;MyPane.YAxis.Scale.MinAuto = false;MyPane.YAxis.Scale.MajorStepAuto = false;MyPane.YAxis.Scale.MinorStepAuto = false;MyPane.YAxis.Scale.FontSpec.FontColor = Color.Yellow;MyPane.YAxis.Scale.FontSpec.Size = 8;MyPane.YAxis.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);MyPane.YAxis.Title.FontSpec.Size = 10;MyPane.YAxis.Title.IsVisible = false;MyPane.YAxis.IsVisible = true;#endregion#region 左侧第二条Y轴 Y轴网格线YAxis yAxis1 = new YAxis("");// yAxis1.IsAxisSegmentVisible = false; //Y轴长线是否可见yAxis1.MajorGrid.IsVisible = true;yAxis1.MajorGrid.IsZeroLine = false;yAxis1.MajorGrid.PenWidth = 0.1f;yAxis1.MajorGrid.DashOn = 4f;yAxis1.MajorGrid.DashOff = 4f;yAxis1.MajorGrid.Color = Color.FromArgb(120, 120, 120);yAxis1.MinorGrid.IsVisible = false;yAxis1.MajorTic.Color = Color.FromArgb(150, 150, 150);yAxis1.MajorTic.IsAllTics = false;yAxis1.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度yAxis1.MinorTic.IsAllTics = false;yAxis1.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度yAxis1.Scale.MaxAuto = false;yAxis1.Scale.MinAuto = false;yAxis1.Scale.MinorStepAuto = false;yAxis1.Scale.MajorStepAuto = false;yAxis1.Scale.FontSpec.FontColor = Color.Lime;yAxis1.Scale.FontSpec.Size = 8;yAxis1.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);yAxis1.Title.FontSpec.Size = 10;yAxis1.IsVisible = true;MyPane.YAxisList.Add(yAxis1);#endregion#region 左侧第三条Y轴 Y轴网格线YAxis yAxis2 = new YAxis("");yAxis2.MajorGrid.IsVisible = true;yAxis2.MajorGrid.IsZeroLine = false;yAxis2.MajorGrid.PenWidth = 0.1f;yAxis2.MajorGrid.DashOn = 4f;yAxis2.MajorGrid.DashOff = 4f;yAxis2.MajorGrid.Color = Color.FromArgb(120, 120, 120);yAxis2.MinorGrid.IsVisible = false;yAxis2.MajorTic.Color = Color.FromArgb(150, 150, 150);yAxis2.MajorTic.IsAllTics = false;yAxis2.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度yAxis2.MinorTic.IsAllTics = false;yAxis2.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度yAxis2.Scale.MaxAuto = false;yAxis2.Scale.MinAuto = false;yAxis2.Scale.MinorStepAuto = false;yAxis2.Scale.MajorStepAuto = false;yAxis2.Scale.FontSpec.FontColor = Color.CornflowerBlue;yAxis2.Scale.FontSpec.Size = 8;yAxis2.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);yAxis2.Title.FontSpec.Size = 10;yAxis2.IsVisible = true;MyPane.YAxisList.Add(yAxis2);#endregion#region 右侧的第一条Y轴MyPane.Y2Axis.MajorGrid.IsVisible = true;MyPane.Y2Axis.MajorGrid.IsZeroLine = false;MyPane.Y2Axis.MajorGrid.PenWidth = 0.1f;MyPane.Y2Axis.MajorGrid.DashOn = 4f;MyPane.Y2Axis.MajorGrid.DashOff = 4f;MyPane.Y2Axis.MajorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.Y2Axis.MinorGrid.IsVisible = false;MyPane.Y2Axis.MajorTic.Color = Color.FromArgb(150, 150, 150);MyPane.YAxis.MajorTic.IsAllTics = false;MyPane.Y2Axis.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度MyPane.Y2Axis.MinorTic.IsAllTics = false;MyPane.Y2Axis.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度MyPane.Y2Axis.Scale.MaxAuto = false;MyPane.Y2Axis.Scale.MinAuto = false;MyPane.Y2Axis.Scale.MinorStepAuto = false;MyPane.Y2Axis.Scale.MajorStepAuto = false;MyPane.Y2Axis.Scale.FontSpec.FontColor = Color.Cyan;MyPane.Y2Axis.Scale.FontSpec.Size = 8;MyPane.Y2Axis.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);MyPane.Y2Axis.Title.FontSpec.Size = 10;MyPane.Y2Axis.IsVisible = true;#endregion#region 右侧第二条Y轴Y2Axis yAxis3 = new Y2Axis("");//Y轴网格线yAxis3.MajorGrid.IsVisible = true;yAxis3.MajorGrid.IsZeroLine = false;yAxis3.MajorGrid.PenWidth = 0.1f;yAxis3.MajorGrid.DashOn = 4f;yAxis3.MajorGrid.DashOff = 4f;yAxis3.MajorGrid.Color = Color.FromArgb(120, 120, 120);yAxis3.MinorGrid.IsVisible = false;yAxis3.MajorTic.Color = Color.FromArgb(150, 150, 150);yAxis3.MajorTic.IsAllTics = false;yAxis3.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度yAxis3.MinorTic.IsAllTics = false;yAxis3.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度yAxis3.Scale.MaxAuto = false;yAxis3.Scale.MinAuto = false;yAxis3.Scale.MinorStepAuto = false;yAxis3.Scale.MajorStepAuto = false;yAxis3.Scale.FontSpec.FontColor = Color.Fuchsia;yAxis3.Scale.FontSpec.Size = 8;yAxis3.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);yAxis3.Title.FontSpec.Size = 10;yAxis3.IsVisible = true;MyPane.Y2AxisList.Add(yAxis3); //添加到Y2AxisList中#endregion#region 右侧第三条Y轴Y2Axis yAxis4 = new Y2Axis("");//Y轴网格线yAxis4.MajorGrid.IsVisible = true;yAxis4.MajorGrid.IsZeroLine = false;yAxis4.MajorGrid.PenWidth = 0.1f;yAxis4.MajorGrid.DashOn = 4f;yAxis4.MajorGrid.DashOff = 4f;yAxis4.MajorGrid.Color = Color.FromArgb(120, 120, 120);yAxis4.MinorGrid.IsVisible = false;yAxis4.MajorTic.Color = Color.FromArgb(150, 150, 150);yAxis4.MajorTic.IsAllTics = false;yAxis4.MajorTic.IsOpposite = false; //隐藏对面的刻度-主刻度yAxis4.MinorTic.IsAllTics = false;yAxis4.MinorTic.IsOpposite = false; //隐藏对面的刻度-小刻度yAxis4.Scale.MaxAuto = false;yAxis4.Scale.MinAuto = false;yAxis4.Scale.MinorStepAuto = false;yAxis4.Scale.MajorStepAuto = false;yAxis4.Scale.FontSpec.FontColor = Color.Red;yAxis4.Scale.FontSpec.Size = 8;yAxis4.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);yAxis4.Title.FontSpec.Size = 10;yAxis4.IsVisible = true; //隐藏MyPane.Y2AxisList.Add(yAxis4); //添加到Y2AxisList中#endregion/* Oscillograph.PanModifierKeys = Keys.Shift; //平移按键,若none,则屏蔽矩形缩放Oscillograph.IsShowContextMenu = false; //显示右键菜单Oscillograph.IsEnableZoom = false; //允许缩放Oscillograph.IsEnableHZoom = false; //允许横向缩放Oscillograph.IsEnableVZoom = false; //允许纵向缩放Oscillograph.IsEnableVPan = false; //允许纵向平移Oscillograph.IsEnableHPan = false; //允许横向平移Oscillograph.IsShowPointValues = false; //显示点的值Oscillograph.IsEnableWheelZoom = false; //禁止鼠标滚动缩放*/Oscillograph.IsShowHScrollBar = true; //水平滚动条Oscillograph.IsAutoScrollRange = true; //滚动范围Oscillograph.IsEnableWheelZoom = true;// Oscillograph.RestoreScale(MyPane);Oscillograph.AxisChange();}#endregionprivate void ChangeBackColorForm(){{MyPane.Chart.Fill.Color = Color.Black;MyPane.Fill.Color = Color.Black;MyPane.Chart.Border.Color = Color.FromArgb(150, 150, 150);MyPane.XAxis.MajorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.XAxis.MinorGrid.Color = Color.FromArgb(120, 120, 120);MyPane.XAxis.MajorTic.Color = Color.FromArgb(150, 150, 150);MyPane.XAxis.MinorTic.Color = Color.FromArgb(150, 150, 150);MyPane.XAxis.Scale.FontSpec.FontColor = Color.FromArgb(150, 150, 150);MyPane.XAxis.Title.FontSpec.FontColor = Color.FromArgb(150, 150, 150);}Oscillograph.Refresh();}#region 轴移动的变量/// <summary>/// 是否移动Y轴/// </summary>private bool IsDragYAxis = false;/// <summary>/// 是否移动X轴/// </summary>private bool IsDragXAxis = false;/// <summary>/// XY轴起始点/// </summary>private int StartPosition = 0;/// <summary>/// 拖拽的XY轴/// </summary>private Axis DragAxis = null;#endregion/// <summary>/// 示波器控件事件注册/// </summary>private void RegisterOscEvent(){//鼠标按下Oscillograph.MouseDownEvent += Oscillograph_MouseDownEvent;//鼠标移动Oscillograph.MouseMoveEvent += Oscillograph_MouseMoveEvent;//松开鼠标(释放)Oscillograph.MouseUpEvent += Oscillograph_MouseUpEvent;//鼠标滚轮滚动Oscillograph.MouseWheel += Oscillograph_MouseWheel;}/// <summary>/// 鼠标按下/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns>true:不会往下继续执行基类的MouseDown功能; false会往下继续执行基类的MouseDown功能</returns>private bool Oscillograph_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e){//判断鼠标按下的位置,是否在轴的位置,以及选中的是哪一个轴this.FindMoveAxis(e, false);if((this.IsDragXAxis || this.IsDragYAxis) && this.DragAxis != null){//不让基类的MouseDown事件继续往下执行return true;}return false;}/// <summary>/// 鼠标移动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns></returns>private bool Oscillograph_MouseMoveEvent(ZedGraphControl sender, MouseEventArgs e){//如果是拖动Y轴if (this.IsDragYAxis && DragAxis!=null){//速度(占的比例)float rate = (e.Y - this.StartPosition) / Oscillograph.GraphPane.Chart.Rect.Height;//距离float diff = rate * (float)(this.DragAxis.Scale.Max - this.DragAxis.Scale.Min);if (Math.Abs(rate) >= 0.01){//Y轴的刻度最大值加上距离this.DragAxis.Scale.Max += diff;//Y轴刻度的最小值加上距离this.DragAxis.Scale.Min += diff;this.StartPosition = e.Y;//刷新曲线图Oscillograph.AxisChange();Oscillograph.Refresh();}}//拖拽X轴if (this.IsDragXAxis && DragAxis != null){float rate = (e.X - this.StartPosition) / Oscillograph.GraphPane.Chart.Rect.Width;float diff = rate * (float)(this.DragAxis.Scale.Max - this.DragAxis.Scale.Min);if (Math.Abs(rate) >= 0.01){this.DragAxis.Scale.Max -= diff;this.DragAxis.Scale.Min -= diff;this.StartPosition = e.X;Oscillograph.AxisChange();Oscillograph.Refresh();}}if ((this.IsDragYAxis || this.IsDragXAxis) && DragAxis != null){return true;}return false;}/// <summary>/// 松开鼠标(释放)/// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns></returns>private bool Oscillograph_MouseUpEvent(ZedGraphControl sender, MouseEventArgs e){this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;return false;}/// <summary>/// 鼠标滚轮滚动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Oscillograph_MouseWheel(object sender, MouseEventArgs e){//判断鼠标按下的位置,是否在轴的位置,以及选中的是哪一个轴int tmpIndexY = this.FindMoveAxis(e, false);if ((this.IsDragXAxis || this.IsDragYAxis) && this.DragAxis != null){//不让基类的MouseDown事件继续往下执行if (tmpIndexY == -1 || !this.DragAxis.IsVisible){//轴不可见return;}//鼠标的坐标PointF centerPoint = new PointF(e.X, e.Y);//缩放灵敏度double zoomFraction = (1 + (e.Delta < 0 ? 1.0 : -1.0)* 0.1);//刻度轴自适应this.ResetAutoScale(this.DragAxis.Scale);//缩放轴this.ZoomAxis(Oscillograph.GraphPane, zoomFraction,centerPoint, this.DragAxis, this.IsDragYAxis, tmpIndexY);this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;return;}}/// <summary>/// 缩放移动轴/// </summary>/// <param name="e">鼠标事件</param>/// <param name="tempIsWheel">滚轮事件true 点击事件false</param>/// <returns>返回Y轴索引</returns>private int FindMoveAxis(MouseEventArgs e, bool tempIsWheel){this.DragAxis = null;this.IsDragXAxis = false;this.IsDragYAxis = false;//Y轴索引int tmpIndexY = -1;#region 判断是否移动左侧Y轴//初始化起始坐标点float tmpStartX = 0;//其中Rect://获取或设置包含由轴(x轴、y轴和y2轴)限定的区域的矩形。//如果手动设置此值,则IsRectAuto值将自动设置为false。//X是获取矩形区域左上角的坐标float tmpEndX = Oscillograph.GraphPane.Chart.Rect.X - 5;//缩放比例float scaleFactor = Oscillograph.GraphPane.CalcScaleFactor();Graphics g = Oscillograph.CreateGraphics();//如果鼠标落下的位置在此范围内 0到 矩形区域左上角的图标//即鼠标落点在Y轴的区域if (e.X > tmpStartX && e.X < tmpEndX){//开始拖拽时Y的坐标值 = 鼠标的Y坐标this.StartPosition = e.Y;//获取Y轴的数量int yAxisCount = Oscillograph.GraphPane.YAxisList.Count;//记录使用的Y轴索引List<int> tmpList = new List<int>();for (int i = yAxisCount - 1; i >= 0; i--){//左侧区域if (!Oscillograph.GraphPane.YAxisList[i].IsVisible){//Y轴不可见yAxisCount--;}else{//记录使用的Y轴索引tmpList.Add(i);}}//就是获取Y左边Y轴的区域除以Y轴的数量 就是每个Y轴的单位宽度float unit = (tmpEndX - tmpStartX) / yAxisCount;unit = 0;//通过循环获取自己要拖拽哪个Y轴for (int i = 0; i < yAxisCount; i++){//计算刻度轴标签的最大宽度float tmpSpecae = Oscillograph.GraphPane.YAxisList[tmpList[i]].CalcSpace(g, Oscillograph.GraphPane, scaleFactor, out float tmpFloat);//如果鼠标所在的X坐标对应Y轴的区域内if (e.X < (unit + tmpSpecae) && e.X > unit){//Y轴索引tmpIndexY = tmpList[i];if (tmpIndexY >= 0){//拖拽Y轴标识改为truethis.IsDragYAxis = true;//拖拽的Y轴的索引就是反顺序的索引this.DragAxis = Oscillograph.GraphPane.YAxisList[tmpIndexY];break;}}unit += tmpSpecae;}}#endregionif (this.IsDragYAxis){//检测选择或滚动Y轴g.Dispose();return tmpIndexY;}#region 判断是否移动右侧Y轴//右侧的X要加上矩形的宽度tmpStartX = Oscillograph.GraphPane.Chart.Rect.Right;tmpEndX = Oscillograph.MasterPane.Rect.Right - 5;if (e.X > tmpStartX && e.X < tmpEndX){//开始拖拽时Y的坐标值 = 鼠标的Y坐标this.StartPosition = e.Y;//获取Y轴的数量int yAxisCount = Oscillograph.GraphPane.Y2AxisList.Count;//就是获取Y左边Y轴的区域除以Y轴的数量 就是每个Y轴的单位宽度float unit = (tmpEndX - tmpStartX) / yAxisCount;//通过循环获取自己要拖拽哪个Y轴for (int i = 0; i < yAxisCount; i++){//如果鼠标所在的X坐标对应Y轴的区域内if (e.X < tmpStartX + unit * (i + 1) && e.X > unit * i + tmpStartX){//拖拽Y轴标识改为truethis.IsDragYAxis = true;//Y轴索引tmpIndexY = i;//拖拽的Y轴的索引就是反顺序的索引this.DragAxis = Oscillograph.GraphPane.Y2AxisList[tmpIndexY];break;}}}#endregionif (this.IsDragYAxis && tmpIndexY > -1){//检测选择或滚动Y轴return (tmpIndexY + Oscillograph.GraphPane.YAxisList.Count-1);}#region 是否拖拽X轴//sender.GraphPane.Chart.Rect.Y 获取左上角的Y坐标 再加上区域高度float tmpStartY = Oscillograph.GraphPane.Chart.Rect.Bottom;float tmpS = Oscillograph.GraphPane.XAxis.CalcSpace(g, Oscillograph.GraphPane, scaleFactor, out float tmpF);float tmpEndY = tmpStartY + tmpS * 0.8f;if (e.Y > tmpStartY && e.Y < tmpEndY){//将拖拽X轴设置为truethis.IsDragXAxis = true;this.StartPosition = e.X;this.DragAxis = Oscillograph.GraphPane.XAxis;}#endregionreturn 0;}/// <summary>/// 缩放轴/// </summary>/// <param name="pane">面板</param>/// <param name="zoomFraction">缩放灵敏度</param>/// <param name="centerPt">鼠标点</param>/// <param name="axis">要缩放的轴</param>/// <param name="IsVertical">垂直true 水平false</param>/// <param name="indexY">y轴索引</param>protected void ZoomAxis(GraphPane pane, double zoomFraction, PointF centerPt,Axis axis, bool IsVertical, int indexY){//在每个轴下对应的数值double x;double x2;double[] y;double[] y2;//将鼠标点坐标转换为 图形内的坐标pane.ReverseTransform(centerPt, out x, out x2, out y, out y2);if (IsVertical){//Y轴if (indexY >= 2){//右侧的axis.Scale.Zoom(zoomFraction, y2[indexY - 2], true);}else{//左侧的axis.Scale.Zoom(zoomFraction, y[indexY], true);}}else{//X轴axis.Scale.Zoom(zoomFraction, x, true);}using (Graphics g = this.CreateGraphics()){pane.AxisChange(g);//g.Dispose();}Oscillograph.Refresh();}/// <summary>/// 单个轴的自适应/// </summary>/// <param name="scale"></param>private void ResetAutoScale(Scale scale){scale.MaxAuto = true;scale.MinAuto = true;scale.MajorStepAuto = true;scale.MinorStepAuto = true;}}
}