2
votes

I have a chart form where I have one chart, but three ChartAreas. Further, each ChartArea can be visible or not, with the intentions that at least one will be visible. The user can also resize the form thus causing the overall chart to be resized, but fortunately not relocated; however the maximum XY ranges can be different due to the resize.

My desire is to be able to perform zoom/unzoom operations on each ChartArea based on a mouse action. For example; hovering over a given ChartArea and using the mousewheel I'd like to zoom/unzoom.

I'm not sure how to determine the geography of a ChartArea. For instance I have the one chart, 3 ChartAreas, then would they be equally spaced with some buffering between? How would I determine the buffer spacing between charts, is that even a property? Same question as to whether or not I'm withing the physical chart space; these are FastLine charts, so I have an X and Y axis and those are labeled. Further, the values of the data can cause the X-Axis labeling to be larger - thus shifting that axis more to the right.

Do I use Axis(XY).PixelPositionToValue and if that value is <0 then I'm not in the ChartArea?

2
If this is a Form Control, then you can see it's Height, Width, and Position. And there should be a MoveOver event or someting.gunr2171

2 Answers

1
votes

You can locate the position of the mouse on the Chart by relying on the MouseMove event (as suggested by gunr2171) and the given ChartArea by relying on its Position property (MSDN link). There are various problems which need to be addressed in order to deliver the kind of positioning you are after (X from left to right and Y from bottom to top; with respect to the frame given by the ChartArea):

  • Correct the Y values, which will be provided "inversely" (from top (0) to bottom (height)).
  • Determine whether the given coordinates (referred to the Chart) are inside the given ChartArea.
  • Convert the coordinates from the Chart reference system to the ChartArea reference system.

First thing is calculating the max./min. values defining the given 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);

In the MouseMove event of the given Chart:

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

NOTE: Hans Passant has provided an interesting link to determine whether the mouse is inside certain ChartArea or not. It might replace the condition on the chart1_MouseMove method, although not the min/max, X/Y calculations required for moving between the different systems of reference (Chart and ChartArea ones) anyway. In any case, you have to make sure about the exact inputs expected by this function (not clearly explained in the provided link), by bearing in mind that 3 different systems of reference are involved (the global one, the one of the Chart and the one of the ChartArea). In this kind of situations, I do prefer to perform the whole calculations "manually", in order to avoid compatibility problems while using different reference systems.

0
votes

I'm a bit late to the party, but I just ran into this problem too. A combination of interesting link and rubber band rectangle proved to be the best solution for me. The full solution allows the user to draw a rubber band rectangle around the area they want to zoom into. The zoom is cancelled if the rectangle goes out of the chart area, or spans over more than one chart area. The zoom is ignored if the elapse time between mouse down and mouse up is less than the double click time. In that case a double click resets the zoom.

The OP is just asking for a way of obtaining the chart area from a mouse click, so I will just show that code segment. Message me if you want the full solution.

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