none
C#でChartコントロールで利用する背景の拡大縮小の追従 RRS feed

  • 質問

  • visual studio2013でグラフを描画しグラフの拡大縮小は行えます。

    このとき背景サイズが元のサイズのまま固定され画像が追従されまさん。

    なにかいい方法はないでしょうか。

     private void comboBoxZoom_SelectedIndexChanged(object sender, EventArgs e)
            {
              
               //Zoom into the X axis
                chart1.ChartAreas[0].AxisX.ScaleView.Zoom(0,Convert.ToDouble(comboBoxZoom.SelectedItem));
                chart1.ChartAreas[0].AxisY.ScaleView.Zoom(0,Convert.ToDouble(comboBoxZoom.SelectedItem));

                //Enable range selection and zooming end user interface
                chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
                chart1.ChartAreas[0].CursorY.IsUserEnabled = true;
                chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
                chart1.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
                chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
                chart1.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
                chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true;
                chart1.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = true;

                //Scroll Ber
                chart1.ChartAreas[0].CursorX.LineColor = Color.Black;
                chart1.ChartAreas[0].CursorX.LineWidth = 1;
                chart1.ChartAreas[0].CursorX.LineDashStyle = ChartDashStyle.Dot;
                chart1.ChartAreas[0].CursorX.Interval = 0;
                chart1.ChartAreas[0].CursorY.LineColor = Color.Black;
                chart1.ChartAreas[0].CursorY.LineWidth = 1;
                chart1.ChartAreas[0].CursorY.LineDashStyle = ChartDashStyle.Dot;
                chart1.ChartAreas[0].CursorY.Interval = 0;
                //スクロールバーの色設定
                chart1.ChartAreas[0].AxisX.ScrollBar.BackColor = Color.White;
                chart1.ChartAreas[0].AxisX.ScrollBar.ButtonColor = Color.FromArgb(70, Color.Silver);
                chart1.ChartAreas[0].AxisX.ScrollBar.LineColor = Color.Black;
                chart1.ChartAreas[0].AxisY.ScrollBar.BackColor = Color.White;
                chart1.ChartAreas[0].AxisY.ScrollBar.ButtonColor = Color.FromArgb(70, Color.Silver);
                chart1.ChartAreas[0].AxisY.ScrollBar.LineColor = Color.Black;
            }

    2016年1月23日 7:02

回答

  • Prepaintイベントで好きなように背景画像を描画することができます。
    その描画処理で拡大縮小やスクロールの影響を受けた座標を計算すれば追従させることができます。

    Image _Image;//どこかで画像は指定しておく
    
    private void chart1_PrePaint(object sender, ChartPaintEventArgs e)
    {
    	Chart chart = (Chart)sender;
    	
    	foreach (ChartArea a in chart.ChartAreas)
    	{
    		//背景画像を描画するのに邪魔な色は消す
    		a.BackColor = Color.Transparent;
    	}
    
    	ChartArea area = e.ChartElement as System.Windows.Forms.DataVisualization.Charting.ChartArea;
    	if (area != null)
    	{
    		float zoom = (float)(area.AxisX.Maximum / Convert.ToDouble(comboBoxZoom.SelectedItem));
    		if (float.IsNaN(zoom) || float.IsInfinity(zoom) || zoom == 0)
    		{
    			return;
    		}
    
    		Graphics g = e.ChartGraphics.Graphics;
    
    		//ChartAreaの描画座標を計算
    		var r = e.Position.ToRectangleF();
    		var x = chart.Width / 100f * r.X;
    		var y = chart.Height / 100f * r.Y;
    		var w = r.Width / 100f * chart.Width;
    		var h = r.Height / 100f * chart.Height;
    		RectangleF areaRectangleF = new RectangleF(x, y, w, h);
    
    		//はみ出たところを描画しないようにクリップ
    		var save = g.Save();
    		e.ChartGraphics.Graphics.SetClip(areaRectangleF);
    
    		//イメージを描画する位置を左上基準と勝手に決める
    		//最大最小の範囲にImageがフィットするという前提で
    		double imageLeft = area.AxisX.IsReversed ? area.AxisX.Maximum : area.AxisX.Minimum;
    		double imageRight = area.AxisX.IsReversed ? area.AxisX.Minimum: area.AxisX.Maximum;
    		double imageTop = area.AxisY.IsReversed ? area.AxisY.Minimum : area.AxisY.Maximum;
    		double imageBottom = area.AxisY.IsReversed ? area.AxisY.Maximum : area.AxisY.Minimum;
    								
    		var pL = (float)area.AxisX.ValueToPixelPosition(imageLeft);
    		var pR = (float)area.AxisX.ValueToPixelPosition(imageRight);
    		var pT = (float)area.AxisY.ValueToPixelPosition(imageTop);
    		var pB = (float)area.AxisY.ValueToPixelPosition(imageBottom);
    		var pW = pR - pL;
    		var pH = pB - pT;
    
    		//ImageはこのRectangleにフィットするように描画
    		RectangleF imageRectangleF = new RectangleF(pL, pT, pW, pH);
    		g.DrawImage(_Image, imageRectangleF);
    
    		g.Restore(save);
    	}
    }
    



    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク momonga98 2016年1月24日 3:29
    2016年1月23日 8:46