经过大量对MsChart的研究,现在实现该功能,即:鼠标点击数据点时,弹出相应信息显示区域,并可自由拖动该区域;双击该信息显示区域,该区域消失。
实现 此功能的关键就是chart控件中的GetToolTipText事件,微软解释是:”在显示工具提示之前发生以获取工具提示文本“。我的理解就是只要鼠标在char控件范围内,该事件就一直跟踪鼠标轨迹,即扫描鼠标指针的坐标X值和Y值;如果指针放到数据点上,就弹出ToolTipText。
对应到具体方法如:private void chart1_GetToolTipText(object sender, ToolTipEventArgs e)
其中ToolTipEventArgs 类的HitTestResult对象,就可以的得到数据点DataPoint的信息:
HitTestResult:获取 HitTestResult 对象,该对象提供了有关引发GetToolTipText事件的图表元素的信息。
Text:获取或设置当鼠标光标停留在图表元素上时所显示的工具提示(如果有)。此属性也可以为此图表元素设置工具提示。
X:获取引发 GetToolTipText 事件时鼠标光标停留的点的 X 坐标。
Y:获取引发 GetToolTipText 事件时鼠标光标停留的点的 Y 坐标。
因此,我的思路是:
在Form中设置一个toolTipEventArgs作为内部属性,一旦指针移动到char里的数据点上,在引发GetToolTipText事件时,将事件中得到的的ToolTipEventArgs赋值给toolTipEventArgs属性,并在点击鼠标的chart1_Click事件中,使用toolTipEventArgs属性中获取的DataPoint信息,填充动态生成的Label的Text。
然后使用Label的MouseDown,MouseMove,MouseUp实现Label的可拖拽。使用Label的MouseDoubleClick实现Label的消除。
代码如下(VS2010):
首先在Form中拖入一个Chart控件,命名为chart1。
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 System.Windows.Forms.DataVisualization.Charting;namespace MsChartTest{ public partial class Form1 : Form { /// <summary> /// 缓存GetToolTipText事件中的ToolTipEventArgs /// </summary> ToolTipEventArgs toolTipEventArgs; //设置数据 List<string> xList = new List<string>() { "x1", "x2", "x3", "x4", "x5" }; List<string> yList = new List<string>() { "1", "2", "3", "4", "1" }; /// <summary> /// Form构造方法 /// </summary> public Form1() { InitializeComponent(); //绑定数据 chart1.Series[0].Points.DataBindXY(xList,yList); //设置Chart样式为折线图 chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line ; chart1.Series[0].BorderWidth = 1; chart1.Series[0].IsValueShownAsLabel = true; //设置数据点样式为圆点 chart1.Series[0].MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle; } private bool isMouseDown = false; private Point mouseOffset; //记录鼠标指针的坐标 private void lbl_ToolTip_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { mouseOffset.X = e.X; mouseOffset.Y = e.Y; isMouseDown = true; } } private void lbl_ToolTip_MouseMove(object sender, MouseEventArgs e) { if (isMouseDown) { int left = ((Label )sender).Left + e.X - mouseOffset.X; int top = ((Label)sender).Top + e.Y - mouseOffset.Y; ((Label)sender).Location = new Point(left, top); } } private void lbl_ToolTip_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isMouseDown = false; } } private void chart1_Click(object sender, EventArgs e) { MouseEventArgs mouseEventArgs = (MouseEventArgs)e; //判断鼠标是否放在了数据点之上 if (mouseEventArgs.X == toolTipEventArgs.X && mouseEventArgs.Y == toolTipEventArgs.Y) { //动态生成Label Label lbl_ToolTip = new Label(); //使用数据点的x值和y值格式化Label的Text lbl_ToolTip.Text = string.Format("X={0};Y={1}", chart1.Series[0].Points[toolTipEventArgs.HitTestResult.PointIndex].AxisLabel, chart1.Series[0].Points[toolTipEventArgs.HitTestResult.PointIndex].YValues[0]); lbl_ToolTip.Location = new Point(mouseEventArgs.X, mouseEventArgs.Y ); lbl_ToolTip.BackColor = Color.LemonChiffon; lbl_ToolTip.BorderStyle = BorderStyle.FixedSingle; //Label订阅相关的可拖拽事件 lbl_ToolTip.MouseDown += new MouseEventHandler(lbl_ToolTip_MouseDown); lbl_ToolTip.MouseMove += new MouseEventHandler(lbl_ToolTip_MouseMove); lbl_ToolTip.MouseUp += new MouseEventHandler(lbl_ToolTip_MouseUp); //Label订阅双击消除事件 lbl_ToolTip.MouseDoubleClick += new MouseEventHandler(lbl_ToolTip_MouseDoubleClick); //这里是保证将自动生成的Label可以放置在chart1之上的关键 this.Controls.Add(lbl_ToolTip); //BringToFront()一定要在this.Controls.Add(lbl_ToolTip)之后,否则不能覆盖chart1 lbl_ToolTip.BringToFront(); } } /// <summary> /// 双击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void lbl_ToolTip_MouseDoubleClick(object sender, MouseEventArgs e) { ((Label)sender).Dispose(); } /// <summary> /// GetToolTipText事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void chart1_GetToolTipText(object sender, System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs e) { //我的理解就是只要鼠标在char控件范围内,该事件就一直跟踪鼠标轨迹,即扫描鼠标指针的坐标X值和Y值 //因此当鼠标指针放置在数据点上时,即e.HitTestResult.ChartElementType == ChartElementType.DataPoint,可将e赋值给toolTipEventArgs属性 if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint) { toolTipEventArgs = e; } } }}
效果如下:
联系客服