MS图表矩形注释宽度,以百分比表示,而不是像素

为什么MS图表的矩形注释宽度是百分比而不是像msdn这样的像素呢? https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.annotation.width(v=vs.110).aspx

这就是msdn所说的获取或设置注释的宽度(以像素为单位)。

我想将宽度设置为像它所说的像素。 我在这里错过了什么吗?

恭喜,您在文档中发现了一个错误! 只需按照Annotation.Height文档的链接即可轻松识别..

Chart控件中的许多其他维度一样, Annotation的维度确实以百分比forms给出 。 这有一个优点,就像许多其他元素一样,它们使用Chart控件非常巧妙地增长和缩小。

因此,如果您将图表的宽度加倍,则基本上会使显示的DataPoints的空间加倍,如果您的Annotation超过了宽度的1/3,那么在调整图表大小之后它仍然会这样做。

这很好。

但不是你想要的……

因此,要将大小设置为固定大小(以像素为单位),您需要执行以下操作:

  • 以百分比计算所需的大小并进行设置
  • 每当您调整图表或其布局的大小时重复

真正的问题是计算:如果您查看Chart.ClientSize您将获得以像素为单位的大小,并获得n个像素,您需要执行以下操作:

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

但是,这并未考虑Chart可能具有的各种元素: AnnotationSize 并未真正计算为图表大小的直接百分比

相反,它被计算为ChartArea CAInnerPlotPosition的百分比。

默认情况下, InnerPlotPosition设置为Auto因此访问其值,例如CA.InnerPlotPosition.Width将返回0f ; 但你可以通过这样做得到(当前!!)值:

 RectangleF IPP = CA.InnerPlotPosition.ToRectangleF(); 

ChartArea本身的Size/Position也是如此:

 RectangleF CAP = CA.Position.ToRectangleF(); 

现在,您可以将这些百分比与( 当前!Chart.ClientSize结合起来,找出实现特定像素大小所需的百分比。

请注意, resize时这些值会发生变化,因为外部附加内容(如LegendAxisLabels等)不会resize,因此它们的相对大小将相对于其包含元素增大或闪烁。

因此, 您需要在每次Resize事件时重新计算 ,或者更好:编写一个函数来为您执行此操作,您可以调用所需的函数。

无论你如何调整Chart大小,结果都是一个Annotation (几乎是由于四舍五入)保持它的大小。

以下是一些有用的function:

这个返回ChartArea当前 ClientRectangle (以像素为单位)

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

这个是类似的,并以像素为单位返回ChartArea's InnerplotPosition的当前ClientRectangle

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

最后一个将像素大小转换为百分比的一个,再次仅在当前有效,即直到下一个大小或布局发生变化..:

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

让我们看一下resize之前和之后的结果:

在此处输入图像描述 在此处输入图像描述

如你所见,尺寸保持不变。

还要注意我在Paint事件中绘制的彩色矩形以说明新function!

这是Paint事件:

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

这是Resize事件:

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

这里的尺寸调整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; } 

是的,我们无法将其设置为%或px,因为属性值设置为double。 其次,pixle = H乘以W.但你只是设置图表的宽度然后你怎么能用pixle设置它? 从根本上说,这是不可能的。 我希望你能明白我的意思。