How to let user create Annotations on MSChart?

前端 未结 1 1893
刺人心
刺人心 2021-01-15 03:46

How do you create an Annotation on-the-run and how do you enable end-user placement with Annotation.BeginPlacement()? I\'ve tried to do this in multiple ways, b

1条回答
  •  孤街浪徒
    2021-01-15 04:10

    You need to calculate the right positions. Remember that the MouseMove will not give you positions (percentages) or values(data) but pixels. You can transform them using the various axis functions. Officially they only work in a xxxPaint event, but during mouse events they also work fine.

    Update: There two ways to do the anchoring:

    • Either by using the 'Positions', i.e. the percentages or the 'Values', i.e. the data values.

    Here is an example of the 1st kind:

        LineAnnotation laNew = null;
    
        private void chart1_MouseDown(object sender, MouseEventArgs e)
        {
            if (cbx_drawAnnotation.Checked)
            {
                Axis ax = chart1.ChartAreas[0].AxisX;
                Axis ay = chart1.ChartAreas[0].AxisY;
                laNew = new LineAnnotation();
                chart1.Annotations.Add(laNew);
                double vx = ax.ValueToPosition(ax.PixelPositionToValue(e.X));
                double vy = ay.ValueToPosition(ay.PixelPositionToValue(e.Y));
                laNew.X = vx;
                laNew.Y = vy;
            }
        }
    
    
        private void chart1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button.HasFlag(MouseButtons.Left) && cbx_drawAnnotation.Checked)
            {
                Axis ax = chart1.ChartAreas[0].AxisX;
                Axis ay = chart1.ChartAreas[0].AxisY;
                double vx = ax.ValueToPosition(ax.PixelPositionToValue(e.X))- laNew.X;
                double vy = ay.ValueToPosition(ay.PixelPositionToValue(e.Y)) - laNew.Y;
                laNew.Width =  Math.Min(100, vx);
                laNew.Height =  Math.Min(100, vy);
                laNew.LineColor = rb_green.Checked ? Color.Green : Color.Red;
                laNew.AllowMoving = true;  // optional
            }
        }
    

    This works fine unles you need to rescale the axis in some way, like changing the axis minimum and/or maximum values.

    • In the case you need to anchor to data values.

    First we need to relate the Annotation to the Axes and also set IsSizeAlwaysRelative to false. Then we can calculate the anchor and size values:

    private void chart1_MouseDown(object sender, MouseEventArgs e)
    {
        if (cbx_drawAnnotation.Checked)
        {
            Axis ax = chart1.ChartAreas[0].AxisX;
            Axis ay = chart1.ChartAreas[0].AxisY;
            laNew = new LineAnnotation();
            chart1.Annotations.Add(laNew);
    
            laNew.IsSizeAlwaysRelative = false;
    
            laNew.AxisX = ax;
            laNew.AxisY = ay;
    
            laNew.AnchorX = ax.PixelPositionToValue(e.X);
            laNew.AnchorY = ay.PixelPositionToValue(e.Y);
    
            laNew.LineColor = rb_green.Checked ? Color.Green : Color.Red;
            laNew.AllowMoving = true;
        }
    }
    
    
    private void chart1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button.HasFlag(MouseButtons.Left) && cbx_drawAnnotation.Checked)
        {
            Axis ax = chart1.ChartAreas[0].AxisX;
            Axis ay = chart1.ChartAreas[0].AxisY;
    
            laNew.Width = ax.PixelPositionToValue(e.X) - laNew.AnchorX;   // values
            laNew.Height = ay.PixelPositionToValue(e.Y) - laNew.AnchorY;  
        }
    }
    

    Note how I now can scale the maximum and also still resize the the chart and the annotations stay with the data points..:

    Update: To restrict the line to the ChartArea add this to the definition in the MouseDown event:

     laNew.ClipToChartArea = chart1.ChartAreas[0].Name;
    

    To prevent an exception from leaving the Chart, add this to the condition in the MouseMove..:

    .. && chart1.ClientRectangle.Contains(e.Location)
    

    0 讨论(0)
提交回复
热议问题