检测鼠标是否在图表区域内

3
我有一个图表,其中有一个图表和三个ChartAreas。 此外,每个ChartArea都可以可见或不可见,意图是至少有一个可见。 用户还可以调整窗体的大小,从而导致整个图表的大小调整,但幸运的是不会被重新定位; 但是由于调整大小,最大XY范围可能会有所不同。
我的愿望是能够根据鼠标操作对每个ChartArea执行缩放/取消缩放操作。 例如; 悬停在给定的ChartArea上并使用鼠标滚轮,我想缩放/取消缩放。
我不确定如何确定ChartArea的地理位置。 例如,我有一个图表,3个ChartAreas,那么它们是否间隔相等,并且之间有一些缓冲区? 我如何确定图表之间的缓冲区间距,这是否是属性? 是否在物理图表空间内,这是相同的问题; 这些都是FastLine图表,因此我有X和Y轴,并且这些轴已标记。 此外,数据的值可能会导致X轴标签更大-从而将该轴向右移动。
我应该使用Axis(XY).PixelPositionToValue,如果该值为<0,则不在ChartArea中吗?

如果这是一个表单 "控件",那么你可以看到它的 "高度"、 "宽度" 和 "位置"。并且应该有一个 "MoveOver" 事件或者类似的东西。 - gunr2171
3
好的,以下是您需要翻译的内容:http://msdn.microsoft.com/en-us/library/dd468025.aspx该链接为微软开发者网络(MSDN)上的网页,提供了有关如何在Windows Communication Foundation(WCF)中使用数据协定的详细信息。您可以学习如何定义、序列化和反序列化数据类型以及如何将它们用于 WCF 服务的参数和返回类型。该页面还提供了有关如何使用各种类型的数据协定的示例代码和指南。 - Hans Passant
2个回答

1
您可以通过依赖 MouseMove 事件 (如 gunr2171 建议的) 和给定的 ChartAreaPosition 属性 (MSDN链接) 来确定鼠标在 Chart 上的位置。为了达到您想要的定位效果(X 左至右,Y 下至上;相对于 ChartArea 给出的框架),需要解决以下各种问题:
  • 矫正 Y 值,这些值将被“倒置”提供(从顶部 (0) 到底部 (高度))。
  • 确定给定坐标(指 Chart 上的坐标)是否在给定的 ChartArea 内。
  • 将坐标从 Chart 参考系转换为 ChartArea 参考系。

首先要计算定义给定 ChartArea 的最大/最小值:

int minX1, minY1, maxX1, maxY1;
minX1 = (int)chart1.ChartAreas[0].Position.X;
maxX1 = (int)(chart1.ChartAreas[0].Position.X + chart1.ChartAreas[0].Position.Width * chart1.Width /100);
minY1 = (int)chart1.ChartAreas[0].Position.Y;
maxY1 = (int)(chart1.ChartAreas[0].Position.Y + chart1.ChartAreas[0].Position.Height * chart1.Height/100);

在给定图表的MouseMove事件中:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
    Point posChart = new Point(e.X, e.Y); //Position of the mouse respect to the chart
    if (posChart.X >= minX1 && posChart.X <= maxX1 && posChart.Y >= minY1 && posChart.Y <= maxY1)
    {
        //The mouse is inside the given area
        //Conversion of the mouse position to the ChartArea reference system, with the corresponding "inversion" of the Y values
        Point posChartArea = new Point(posChart.X - minX1, Math.Abs((posChart.Y - minY1) - maxY1));
    }
}

注意:Hans Passant提供了一个有趣的链接,可以确定鼠标是否在特定的ChartArea内。它可能会替换chart1_MouseMove方法中的条件,但不会替换在不同参考系统(Chart和ChartArea)之间移动所需的最小/最大、X/Y计算。无论如何,在任何情况下,您都必须确保此函数期望的确切输入(在提供的链接中没有清楚地解释),并牢记涉及3个不同的参考系统(全局参考系统、Chart参考系统和ChartArea参考系统)。在这种情况下,我更喜欢手动执行所有计算,以避免在使用不同参考系统时出现兼容性问题。


感谢大家的建议,特别是varocarbas。我也同意Hans Passant提供的链接是一个有趣的函数,实际上可以从那里开始进行一些实验。 - rtm

1
我有点晚了,但我也遇到了这个问题。 有趣的链接橡皮筋矩形 的结合对我来说是最好的解决方案。完整的解决方案允许用户在他们想要缩放的区域周围画一个橡皮筋矩形。如果矩形超出图表区域或跨越多个图表区域,则缩放将被取消。如果鼠标按下和鼠标松开之间的时间小于双击时间,则忽略缩放。在这种情况下,双击将重置缩放。

OP只是询问从鼠标单击中获取图表区域的方法,因此我将展示该代码段。如果您需要完整的解决方案,请给我发信息。

private Point mouseDown = Point.Empty;
private Stopwatch clickTimer = null;
private ChartArea chartAreaToZoom = null;

private void chart1_MouseDown(object sender, MouseEventArgs e)
{
    HitTestResult result = chart1.HitTest(e.X, e.Y);
    if (result.ChartArea != null)
    {
        chartAreaToZoom = result.ChartArea;
        mouseDown = e.Location;
        clickTimer = Stopwatch.StartNew();
    }
}

晚了一点,但并不算太晚——这个问题有一个更加优雅的解决方案。 - gus27

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接