这是个好主意。
最简单的方法是将图像绘制在Paint
图表中的事件,也许PrePaint
.
让我们去工作吧..我们将使用DrawImage https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx重载允许我们缩放和裁剪。为此我们需要两个矩形。
第一个挑战是始终获得正确的目标矩形。
为此我们需要将InnerPlotPosition
从相对位置到绝对像素。
这两个功能将有助于:
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);
}
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);
}
使用这些数字设置目标矩形就非常简单:
Rectangle tgtR = Rectangle.Round(new RectangleF(ipr.Left, ipr.Bottom - 15, ipr.Width, 15));
你可以选择你喜欢的高度..
下一个挑战是源矩形。
如果没有缩放,它就会简单地是:
Rectangle srcR = new Rectangle( 0, 0, bmp.Width, bmp.Height);
但对于缩放和平移,我们需要对其进行缩放;为此,我们可以使用 x 轴和ScaleView
's Minimum
and Maximum
values.
我们计算轴上第一个和最后一个点的因子:
double f1 = ax.ScaleView.ViewMinimum / (ax.Maximum - ax.Minimum);
double f2 = ax.ScaleView.ViewMaximum / (ax.Maximum - ax.Minimum);
现在我们得到源矩形可能是这样的:
int x = (int)(bmp.Width * f1);
int xx = (int)(bmp.Width * f2);
Rectangle srcR = new Rectangle( x, 0, xx - x, bmp.Height);
让我们把它放在一起:
private void chart_PrePaint(object sender, ChartPaintEventArgs e)
{
// a few short names
Graphics g = e.ChartGraphics.Graphics;
ChartArea ca = chart.ChartAreas[0];
Axis ax = ca.AxisX;
// pixels of plot area
RectangleF ipr = InnerPlotPositionClientRectangle(chart, ca);
// scaled first and last position
double f1 = ax.ScaleView.ViewMinimum / (ax.Maximum - ax.Minimum);
double f2 = ax.ScaleView.ViewMaximum / (ax.Maximum - ax.Minimum);
// actual drawing with the zooming overload
using (Bitmap bmp = (Bitmap)Bitmap.FromFile(imagePath))
{
int x = (int)(bmp.Width * f1);
int xx = (int)(bmp.Width * f2);
Rectangle srcR = new Rectangle( x, 0, xx - x, bmp.Height);
Rectangle tgtR = Rectangle.Round(
new RectangleF(ipr.Left , ipr.Bottom - 15, ipr.Width, 15));
g.DrawImage(bmp, tgtR, srcR, GraphicsUnit.Pixel);
}
}
一些注意事项:
对于后一种解决方案,您需要根据缩放状态偏移 y 位置。又快又脏:int yoff = (ax.ScaleView.IsZoomed ? 12 : 5);
。为了避免出现黑色条纹,还可以将轴设置为透明或 Chart.BackColor..
Update:
您还可以恢复使用StripLine
。它可以扩展其BackgroundImage
每当更改比例视图时(即缩放或平移时),您都必须创建合适的图像。为此,上述大部分代码将用于创建新图像。看这个帖子 https://stackoverflow.com/questions/49937962/combine-barchart-and-pointchart/49939521#49939521有关添加和替换不同的示例NamedImage
到图表! (相关部分接近标记图像的结尾!)
事实上,我发现这种方式是最好的解决方案,并添加了第二个答案。