MS Chart Rectangular Annotation width in percent and not pixel

╄→гoц情女王★ 提交于 2019-12-17 06:58:08

问题


why is it that the MS chart rectangular annotation width is in percent and not pixel like msdn says it is? https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.annotation.width(v=vs.110).aspx

This is what msdn says Gets or sets the width, in pixels, of an annotation.

I'd like to set my width to be pixels like it states. Am I missing something here?


回答1:


Congratulations, you have found a bug in the documentation! Easy to spot simply by following the link to the Annotation.Height docs..

The dimensions of an Annotation, as many others in a Chart control, are indeed given in percentages. This has the advantage that they quite cleverly grow and shrink with the Chart control just like many other elements.

So if you double the width of the chart you basically double the space for the shown DataPoints and if your Annotation went over a 1/3 of the width before it will still do that after you have resized the chart..

Which is nice.

But not what you wanted..

So to set the size to a fixed size in pixels you need to do this:

  • Calculate the size you want in percentages and set it
  • Repeat whenever you resize the chart or its layout

The real problem is the calculation: If you look at the Chart.ClientSize you get the size in pixels and to get n pixels you need to do something like this:

float WidthInPercent = 100f * n / Chart.ClientSize.width;

This however does not take into account the various elements your Chart probably has : The Size of an Annotation is not really calculated as direct percentages of the Chart's size.

Instead it is calulated as percentages of the InnerPlotPosition of the ChartArea CA.

InnerPlotPosition by default is set to Auto so accessing its values, e.g. CA.InnerPlotPosition.Width will return 0f; but you can get at the (current!!) values by doing this:

RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();

The same goes for the Size/Position of the ChartArea itself:

RectangleF CAP = CA.Position.ToRectangleF();

Now you can combine these percentages with the (current!) Chart.ClientSize to find out which percentage you need to achieve a certain pixel size..

Note that these values will change when resizing because the outer extras, like Legend and Axis and Labels etc. will not resize, so their relative sizes will grow or shink in relation to their containing elements..

So you need to recalculate upon each Resize event, or, better: write a function to do it for you which you can call wheneber needed..

The result is an Annotation that will (pretty much, due to rounding) maintain its size, no matter how you resize the Chart..

Here are some helpful functions:

This one returns the current ClientRectangle of a ChartArea in pixels

RectangleF ChartAreaClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF CAR = CA.Position.ToRectangleF();
    float pw = chart.ClientSize.Width / 100f;
    float ph = chart.ClientSize.Height / 100f;
    return new RectangleF(pw * CAR.X, ph * CAR.Y, pw * CAR.Width, ph * CAR.Height);
}

This one is similar and returns the current ClientRectangle of a ChartArea's InnerplotPosition in pixels:

RectangleF InnerPlotPositionClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();
    RectangleF CArp = ChartAreaClientRectangle(chart, CA);

    float pw = CArp.Width / 100f;
    float ph = CArp.Height / 100f;

    return new RectangleF(CArp.X + pw * IPP.X, CArp.Y + ph * IPP.Y, 
                            pw * IPP.Width, ph * IPP.Height);
}

Finally one that converts a size in pixels to one in percentages, again valid only currently, i.e. until the next changes in size or layout..:

SizeF Pixels2Percent( ChartArea CA, int w, int h)
{
    RectangleF IPPR = InnerPlotPositionClientRectangle(chart1, CA);

    float pw = 100f * w / IPPR.Width ;
    float ph = 100f * h / IPPR.Height ;

    return new SizeF(pw, ph);
}

Lets have a look at the result before and after some resizing:

As you can see the size stay the same.

Also note the colored rectangles I draw in the Paint event to demostrate the new functions!

Here is the Paint event:

private void chart1_Paint(object sender, PaintEventArgs e)
{
    ChartArea CA = chart1.ChartAreas[0];
    e.Graphics.DrawRectangle(Pens.Violet, 
               Rectangle.Round(ChartAreaClientRectangle(chart1, CA)));
    e.Graphics.DrawRectangle(Pens.LimeGreen, 
               Rectangle.Round(InnerPlotPositionClientRectangle(chart1, CA)));
}

Here is the Resize event:

private void chart1_Resize(object sender, EventArgs e)
{
    sizeAnn(ra, new Size(24, 36));
}

And here the sizing function:

void sizeAnn(RectangleAnnotation ra, Size sz)
{
    ChartArea CA = chart1.ChartAreas[0];
    SizeF pixelPercent = Pixels2Percent(CA, sz.Width, sz.Height);
    ra.Width = pixelPercent.Width;
    ra.Height = pixelPercent.Height;
}



回答2:


Yes, we cannot set it in % or px as the property value is set to double. Secondly, pixle = H multiplied by W. but you are only setting the width of chart then how can you set it in pixle? It fundamentally not possible. I hope you will understand what I mean.




回答3:


I know the OP wanted to set the width in pixels, but in case some people (like me) want to set the width neither in pixels nor in %, but according to the actual values, just set :

annotation.IsSizeAlwaysRelative = False
annotation.Width = whatEverValue


来源:https://stackoverflow.com/questions/36491231/ms-chart-rectangular-annotation-width-in-percent-and-not-pixel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!