C#GDI+自定義繪製曲線圖表控制元件DataChart 簡單實現 C#GDI+ 繪製線段(實線或虛線)、矩形、字串、圓、橢圓
阿新 • • 發佈:2018-12-02
C#GDI+自定義繪製曲線圖表控制元件DataChart
這裡只說明在計算刻度和曲線繪製的時候 只提供思路,只是做了下簡單的計算,不喜勿噴 還望見諒,高手直接飄過吧。這個要做好,還是需要研究研究演算法的,比如刻度隨著控制元件的大小發生改變的時候計算不同的值,根據刻度範圍來計算刻度以及刻度值等,這裡沒有研究,製作簡單的繪製,讓其知道自定義曲線控制元件的畫法,對於新手來講應該是有一些幫助的。有時間我把研究過後的演算法加上做一個通用可靠一點的控制元件分享。
例子如下圖所示
首先百度一張圖片,就按照它的樣子來繪製
DataChart控制元件製作
在繪製曲線控制元件之前首先得 C#GDI+ 繪製線段(實線或虛線)、矩形、字串、圓、橢圓
1.新增一個使用者控制元件
2.重寫OnPaint方法
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics graphics = e.Graphics; //繪製程式碼部分。。。 }
3.繪製繪圖區域
1 #regionView Code繪圖區域 2 3 int plotBorder = 0; 4 if (this.plotBorderWith % 2 == 0) 5 plotBorder = this.plotBorderWith / 2; 6 else 7 plotBorder = this.plotBorderWith / 2 + 1; 8 9 int plotWidth = this.Width - this.Padding.Left - this.Padding.Right - this.plotBorderWith; 10 int plotHeitht = this.Height - this.Padding.Top - this.Padding.Bottom - this.plotBorderWith; 11 12 13 Rectangle plotArea = new Rectangle( 14 this.Padding.Left + plotBorder, 15 this.Padding.Top + plotBorder, 16 plotWidth, 17 plotHeitht); 18 19 using (SolidBrush brush = new SolidBrush(this.plotBackColor)) 20 { 21 graphics.FillRectangle(brush, plotArea); 22 } 23 24 #endregion
4.繪製曲線區域
1 #region 繪製曲線區域 2 3 int borderwith = 0; 4 if (this.gridBorderWith % 2 == 0) 5 borderwith = this.gridBorderWith / 2; 6 else 7 borderwith = this.gridBorderWith / 2; 8 9 int gridWith = this.Width - this.Padding.Left - this.Padding.Right - this.FontHeight - this.FontHeight - this.gridBorderWith - 2 * this.plotBorderWith; 10 int gridHeight = this.Height - this.FontHeight - 2 * this.FontHeight - this.gridBorderWith; 11 12 Rectangle rectangle = new Rectangle( 13 this.Padding.Left + this.FontHeight + this.FontHeight + this.plotBorderWith + this.gridBorderWith / 2, 14 this.Padding.Top + this.FontHeight, 15 gridWith, 16 gridHeight); 17 18 using (SolidBrush solidGridBrush = new SolidBrush(this.gridBackColor)) 19 { 20 graphics.FillRectangle(solidGridBrush, rectangle); 21 } 22 using (Pen penGrid = new Pen(this.gridBorderColor, this.gridBorderWith)) 23 { 24 graphics.DrawRectangle(penGrid, rectangle); 25 } 26 #endregionView Code
5.繪製文字區域
1 #region 繪製文字區域 2 3 SizeF szfTitle; 4 SizeF szfyLabel; 5 SizeF szfxLabel; 6 7 szfTitle = graphics.MeasureString(this.title, this.Font); 8 szfyLabel = graphics.MeasureString(this.yLabel, this.Font); 9 szfxLabel = graphics.MeasureString(this.xLabel, this.Font); 10 11 //繪製標題 12 if (this.title != null) 13 { 14 int strLeft = rectangle.X + rectangle.Width / 2 - (int)szfTitle.Width / 2; 15 int strHeight = this.Padding.Top + this.plotBorderWith; 16 17 graphics.DrawString(this.title, this.Font, Brushes.Black, strLeft, strHeight); 18 } 19 //繪製垂直方向文字 20 if (this.yLabel != null) 21 { 22 graphics.TranslateTransform(0, this.Height); //座標平移 23 graphics.RotateTransform(-90); //座標旋轉 24 25 int strLeft = 0; 26 if (this.xLabel != "") 27 strLeft = this.Padding.Bottom + this.gridBorderWith + 2 * (int)szfxLabel.Height + rectangle.Height / 2 - (int)szfyLabel.Width / 2; 28 else 29 strLeft = this.Padding.Bottom + this.gridBorderWith + (int)szfxLabel.Height + rectangle.Height / 2 - (int)szfyLabel.Width / 2; 30 31 int strHeight = 0; 32 33 graphics.DrawString(this.yLabel, this.Font, Brushes.Black, strLeft, strHeight); 34 35 graphics.RotateTransform(90); 36 graphics.TranslateTransform(0, -this.Height); 37 38 } 39 //繪製水平方向文字 40 if (this.xLabel != null) 41 { 42 int strLeft = rectangle.X + rectangle.Width / 2 - (int)szfxLabel.Width / 2; 43 int strHeight = rectangle.Y + rectangle.Height + (int)szfxLabel.Height; 44 45 graphics.DrawString(this.xLabel, this.Font, Brushes.Black, strLeft, strHeight); 46 } 47 #endregionView Code
6.繪製座標軸
這裡提供思路,沒有仔細去計算,
1 #region x軸 2 3 double scale = (this.xMax - this.xMin) / rectangle.Width; 4 5 int number = 10; //將x軸分為10份實際根據控制元件的大小來做分配,這裡簡單舉例10份為例 6 double perPixel = rectangle.Width / number; //每一份的佔用的畫素寬度 7 double value = 100; //間隔值 這裡只是寫測試例子直接寫死了,按照使用來講不能這麼幹有時間了,這是個演算法問題,重新補上 8 9 int position = 0; 10 double positionValue = this.xMin; 11 using (Pen pen = new Pen(this.gridLineColor, 1)) 12 { 13 for (int i = 0; i < number; i++) 14 { 15 pen.DashStyle = DashStyle.Solid; 16 17 //x軸刻度 18 19 graphics.DrawLine(pen, 20 rectangle.X + position, 21 rectangle.Y + rectangle.Height, 22 rectangle.X + position, 23 rectangle.Y + rectangle.Height - 8); 24 25 26 string scaleValue = positionValue.ToString("F0"); 27 SizeF szfValue = graphics.MeasureString(scaleValue, this.Font); 28 29 int strX = rectangle.X + position - (int)szfValue.Width / 2; 30 int strY = rectangle.Y + rectangle.Height; 31 32 //x軸刻度值 33 graphics.DrawString(scaleValue, this.Font, Brushes.Black, strX, strY); 34 35 positionValue += value; 36 position += (int)perPixel; 37 } 38 39 } 40 41 #endregion 42 43 #region y軸 44 double scaley = (this.yMax - this.yMin) / this.Width; 45 46 int numbery = 6; 47 double perPixelY = rectangle.Height / numbery; 48 double valueYinterval = 10; 49 50 int positiony = 0; 51 double positionValueY = this.yMin; 52 using (Pen pen = new Pen(this.gridLineColor, 1)) 53 { 54 for (int i = 0; i <= numbery; i++) 55 { 56 57 pen.DashStyle = DashStyle.Solid; 58 59 //y軸刻度 60 61 graphics.DrawLine(pen, 62 rectangle.X, 63 rectangle.Y + rectangle.Height - positiony, 64 rectangle.X + 8, 65 rectangle.Y + rectangle.Height - positiony); 66 67 68 string scaleValueY = positionValueY.ToString("F0"); 69 SizeF szfValue = graphics.MeasureString(scaleValueY, this.Font); 70 71 int strX = rectangle.X - (int)szfValue.Width; 72 int strY = rectangle.Y + rectangle.Height - positiony - (int)szfValue.Height/2; 73 74 //x軸刻度值 75 graphics.DrawString(scaleValueY, this.Font, Brushes.Black, strX, strY); 76 positionValueY += valueYinterval; 77 positiony += (int)perPixelY; 78 } 79 80 } 81 #endregionView Code
7.繪製曲線
這裡繪製曲線只提供思路,沒有仔細研究演算法
1 #region 繪製曲線 2 3 if (x == null || y == null) return; 4 5 float scaleX = (float)(rectangle.Width / (this.xMax - this.xMin)); 6 float scaleY = (float)(rectangle.Height / (this.yMax - this.yMin)); 7 8 PointF[] points = new PointF[x.Length]; 9 10 for (int i = 0; i < this.x.Length; i++) 11 { 12 points[i] = new PointF( 13 (float)((this.x[i] - this.xMin) * scaleX + rectangle.X), 14 rectangle.Y + rectangle.Height - (float)((this.y[i] - this.yMin) * scaleY)); 15 } 16 17 using (Pen pen = new Pen(this.curveColor)) 18 { 19 graphics.DrawLines(pen, points); 20 } 21 22 #endregionView Code
8.效果展示
9.程式原始碼下載