Click here to Skip to main content
15,894,146 members
Home / Discussions / C#
   

C#

 
GeneralRe: Initialization in web services Pin
Nick Parker27-Jul-04 9:28
protectorNick Parker27-Jul-04 9:28 
GeneralCustom VS.NET Wizard query Pin
Michael P Butler27-Jul-04 3:30
Michael P Butler27-Jul-04 3:30 
GeneralRe: Custom VS.NET Wizard query Pin
Heath Stewart27-Jul-04 11:18
protectorHeath Stewart27-Jul-04 11:18 
GeneralRe: Custom VS.NET Wizard query Pin
Michael P Butler28-Jul-04 1:33
Michael P Butler28-Jul-04 1:33 
GeneralActive Directory Exception Pin
vcorn26-Jul-04 20:36
vcorn26-Jul-04 20:36 
GeneralRe: Active Directory Exception Pin
Dave Kreskowiak27-Jul-04 6:38
mveDave Kreskowiak27-Jul-04 6:38 
GeneralRe: Active Directory Exception Pin
vcorn27-Jul-04 19:44
vcorn27-Jul-04 19:44 
Generalproblems with drawing a PieChart Pin
Pain_Elemental26-Jul-04 20:28
Pain_Elemental26-Jul-04 20:28 
Hi all,
I am currently working on a class that draws a Piechart and a legend.

The class offers the possibility to get a bitmap of the chart and to get a bitmap of the legend:

//fill datasource with some test data
PieChartDataSource dataSource = new PieChartDataSource();
dataSource.Add(new PieSliceData("Running", 1841200, Color.Green));
dataSource.Add(new PieSliceData("Waiting", 290000, Color.Blue));
dataSource.Add(new PieSliceData("Blocked", 181000, Color.Yellow));
dataSource.Add(new PieSliceData("Interruption", 62000, Color.Orange));
dataSource.Add(new PieSliceData("Fault", 45000, Color.Red));

PieChart chart = new PieChart(dataSource);
Bitmap chartBmp = chart.DrawChart(new Size(800,600));
chartBmp.Save(@"d:\chart.bmp");

Bitmap legendBmp = chart.DrawLegend();
legendBmp.Save(@"d:\legend.bmp");




I currently trying to draw the legend and the chart in one bitmap. Currently the legend is drawn in the bitmap, but the chart's size is not decreased yet, so it always draw on top of the legend. Have to fix this later...


But now to my problem:
I can now get a bitmap of the chart with a legend
PieChart chart = new PieChart(dataSource);
chart.DrawLegendInChart = true;
chart.LegendPosition = Position.top;
Bitmap chartBmp = chart.DrawChart(new Size(800,600));
chartBmp.Save(@"d:\chart.bmp");


and I can also get a seperate bitmap of the legend:
Bitmap legendBmp = chart.DrawLegend();
legendBmp.Save(@"d:\legend.bmp");



Both code snippets work fine, but if I execute both snippets (one after the other)
PieChart chart = new PieChart(dataSource);
chart.DrawLegendInChart = true;
chart.LegendPosition = Position.top;
Bitmap chartBmp = chart.DrawChart(new Size(800,600));
chartBmp.Save(@"d:\chart.bmp");

Bitmap legendBmp = chart.DrawLegend();
legendBmp.Save(@"d:\legend.bmp");



then I get an exception in DrawLegend() method.
This call
graphics.DrawString(strText, m_FontLegend, blackBrush, iStartX, iStartY);


throws the exception:
TargetSite.DeclaringType: System.Drawing.Graphics
TargetSite.Name: CheckErrorStatus
Message: Invalid parameter used


But how is it possible that this code works if I call it without drawing the chart with legend before?



I appreciate any help solving this problem!

Here is the complete code of my Piechart:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;

namespace Charts
{
	#region enums
	public enum Position{top, bottom, left, right};
	#endregion
	
	/// <summary>
	/// Holds data of one single slice of the PieChart
	/// </summary>
	public class PieSliceData
	{
		#region fields
		string m_strName;
		double m_dValue;
		Color m_Color;
		#endregion

		#region constructors
		public PieSliceData(string strName, double dValue, Color color)
		{
			m_strName=strName;
			m_dValue=dValue;
			m_Color=color;
		}
		#endregion

		#region properties
		public string Name
		{
			get
			{
				return m_strName;
			}
		}

		public double Value
		{
			get
			{
				return m_dValue;
			}
		}

		public Color SliceColor
		{
			get
			{
				return m_Color;
			}
		}
		#endregion
	}
	
	/// <summary>
	/// A collection of PieSliceData
	/// </summary>
	public class PieChartDataSource
	{
		#region fields
		ArrayList m_List;
		#endregion

		#region constructors
		public PieChartDataSource()
		{
			m_List = new ArrayList();
		}
		#endregion

		#region methods
		public void Add(PieSliceData sliceData)
		{
			m_List.Add(sliceData);
		}

		public void RemoveAt(int iIndex)
		{
			m_List.RemoveAt(iIndex);
		}

		public IEnumerator GetEnumerator()
		{
			return m_List.GetEnumerator();
		}
		#endregion

		#region properties
		/// <summary>
		/// Gets the number of PieSlices in the PieSliceDataSource
		/// </summary>
		public int Count
		{
			get
			{
				return m_List.Count;
			}
		}
		#endregion

		#region operators
		public PieSliceData this[int index]
		{
			get
			{
				return (PieSliceData) m_List[index];
			}
		}
		#endregion
	}
	
	/// <summary>
	/// Draw a pie chart using the given information.
	/// </summary>
	public class PieChart
	{
		#region fields
		//chart variables
		PieChartDataSource m_DataSource;
		Color m_BGColor;

		//legend variables
		float m_FontSizeLegend;
		Font m_FontLegend;
		bool m_bDrawLegendInChart;
		Position m_LegendPosition;
		#endregion
		
		#region constructors
		public PieChart(PieChartDataSource dataSource)
		{
			m_DataSource = dataSource;
			m_BGColor = Color.White;
			
			m_FontSizeLegend = 10.0f;
			m_FontLegend = new Font("Verdana", m_FontSizeLegend);
			m_bDrawLegendInChart = false;
			m_LegendPosition = Position.bottom;
		}
		#endregion
		
		#region methods
		/// <summary>
		/// draws a chart in a bitmap
		/// </summary>
		/// <param name="size">size of the bitmap</param>
		/// <returns>a bitmap that holds the chart</returns>
		public Bitmap DrawChart(Size size)
		{
			// Create a new bitmap
			Bitmap bitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb);
			Graphics graphics = Graphics.FromImage(bitmap);
			
			//draw chart in bitmap
			DrawChart(graphics, size);

			return bitmap;
		}

		/// <summary>
		/// draws a chart
		/// </summary>
		/// <param name="graphics">graphics object to draw</param>
		/// <param name="size">desired size of the chart</param>
		public void DrawChart(Graphics graphics, Size size)
		{
			//color background
			SolidBrush brush = new SolidBrush(m_BGColor);
			graphics.FillRectangle(brush, 0, 0, size.Width, size.Height);
			brush.Dispose();

			//draw legend
			if(m_bDrawLegendInChart == true)
			{
				Size legendSize = CalculateLegendSize(graphics);
				
				switch(m_LegendPosition)
				{
					case Position.top:
					{
						//place legen at top middle
						int iLegendOriginX = Convert.ToInt32((size.Width/2) - (legendSize.Width/2));
						int iLegendOriginY = 5;
						DrawLegend(graphics,new Point(iLegendOriginX,iLegendOriginY), legendSize);
					}
						break;
					case Position.bottom:
					{
					}
						break;
					case Position.left:
					{
					}
						break;
					case Position.right:
					{
					}
						break;
				}
			}

			//sum the values to get the total
			double total = 0.0;
			for(int i = 0; i < m_DataSource.Count; i++)
			{
				total+=m_DataSource[i].Value;
			}

			//draw the pie chart
			float start = 0.0f;
			float end = 0.0f;
			double current = 0.0;
			for(int i = 0; i < m_DataSource.Count; i++)
			{
				current += m_DataSource[i].Value;
				start = end;
				end = (float) (current / total) * 360.0f;
				
				SolidBrush sliceBrush = new SolidBrush(m_DataSource[i].SliceColor);
				graphics.FillPie(sliceBrush, 0.0f, 0.0f, size.Width, size.Height, start, end - start);
				sliceBrush.Dispose();
			}
		}

		/// <summary>
		/// draws the chart's legend into a bitmap
		/// </summary>
		/// <param name="size">size of the bitmap</param>
		/// <returns>bitmap that holds the legend</returns>
		public Bitmap DrawLegend()
		{
			// Create a dummy bitmap to get a graphics object
			Bitmap bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
			Graphics dummyGraphics = Graphics.FromImage(bitmap);

			Size legendSize = CalculateLegendSize(dummyGraphics);

			//now create the actual bitmap
			bitmap = new Bitmap(legendSize.Width, legendSize.Height, PixelFormat.Format32bppArgb);
			Graphics graphics = Graphics.FromImage(bitmap);

			//now draw the legend
			DrawLegend(graphics, new Point(0,0), bitmap.Size);

			return bitmap;
		}

		/// <summary>
		/// draws the chart's legend
		/// </summary>
		/// <param name="graphics">graphics object to draw</param>
		/// <param name="origin">start point for drawing</param>
		/// <param name="size">desired size of the legend</param>
		public void DrawLegend(Graphics graphics, Point origin, Size size)
		{
			//color background
			SolidBrush brush = new SolidBrush(m_BGColor);
			graphics.FillRectangle(brush, origin.X, origin.Y, size.Width, size.Height);
			brush.Dispose();

			//draw a line around the bitmap
			graphics.DrawRectangle(new Pen(Color.Black, 2), origin.X, origin.Y, size.Width, size.Height);
			
			//create brush for text
			Brush blackBrush = Brushes.Black;
			
			//draw little rectangles with the appropriate color and write the legend text 
			for(int i = 0; i < m_DataSource.Count; i++)
			{
				SolidBrush sliceBrush = new SolidBrush(m_DataSource[i].SliceColor);

				graphics.FillRectangle(sliceBrush, origin.X + 5, origin.Y + 5 + (m_FontLegend.Height * i), 10, 10);
				
				string strText = m_DataSource[i].Name +": "+ m_DataSource[i].Value.ToString();
				int iStartX = origin.X + 20;
				int iStartY = origin.Y + 1 + (m_FontLegend.Height * i);
				graphics.DrawString(strText, m_FontLegend, blackBrush, iStartX, iStartY);
			
				sliceBrush.Dispose();
			}
	
			//don't forget to dispose the text brush
			blackBrush.Dispose();
		}
		
		/// <summary>
		/// calculates the size that is required for a bitmap of the legend
		/// </summary>
		/// <param name="graphics">graphis object to measure the string sizes</param>
		/// <returns>required size</returns>
		private Size CalculateLegendSize(Graphics graphics)
		{
			float fRequiredSizeX = 0;

			//add start point of strings, because this is on the right of the little colored rectangles
			fRequiredSizeX = fRequiredSizeX + 20;

			//check for the longest string and sum up height
			float fLongestString = 0.0f;
			float fRequiredHeight = 0.0f;
			
			for(int i = 0; i < m_DataSource.Count; i++)
			{
				SizeF stringSize = graphics.MeasureString(m_DataSource[i].Name +": "+ m_DataSource[i].Value.ToString(), m_FontLegend);
				if( stringSize.Width > fLongestString)
				{
					fLongestString = stringSize.Width;
				}
				fRequiredHeight += stringSize.Height;
			}

			fRequiredSizeX += fLongestString;

			return new Size(Convert.ToInt32(fRequiredSizeX), Convert.ToInt32(fRequiredHeight));
		}

		#endregion

		#region properties
		/// <summary>
		/// gets or sets a the background color of the chart
		/// </summary>
		public Color BGColor
		{
			get
			{
				return m_BGColor;
			}
			set
			{
				m_BGColor = value;
			}
		}

		/// <summary>
		/// gets or sets a bool to control if the legend should be drawn together with the chart
		/// </summary>
		public bool DrawLegendInChart
		{
			get
			{
				return m_bDrawLegendInChart;
			}
			set
			{
				m_bDrawLegendInChart = value;
			}
		}

		/// <summary>
		/// gets or sets the position of the legend in relation to the chart
		/// </summary>
		public Position LegendPosition
		{
			get
			{
				return m_LegendPosition;
			}
			set
			{
				m_LegendPosition = value;
			}
		}
		#endregion
	}
}

GeneralRe: problems with drawing a PieChart Pin
Heath Stewart27-Jul-04 11:07
protectorHeath Stewart27-Jul-04 11:07 
GeneralRe: problems with drawing a PieChart Pin
Pain_Elemental28-Jul-04 5:50
Pain_Elemental28-Jul-04 5:50 
Generalsupporting localization Pin
samithas26-Jul-04 18:19
samithas26-Jul-04 18:19 
GeneralRe: supporting localization Pin
Heath Stewart26-Jul-04 18:32
protectorHeath Stewart26-Jul-04 18:32 
GeneralIssue on replacing WebBrowser context menu Pin
w1424326-Jul-04 16:26
w1424326-Jul-04 16:26 
GeneralRe: Issue on replacing WebBrowser context menu Pin
Heath Stewart26-Jul-04 18:20
protectorHeath Stewart26-Jul-04 18:20 
Generalprinting a form Pin
stevemasters2226-Jul-04 15:31
stevemasters2226-Jul-04 15:31 
GeneralBinding DataView to MSChart Pin
Kuan Wai Mun26-Jul-04 15:04
Kuan Wai Mun26-Jul-04 15:04 
GeneralRe: Binding DataView to MSChart Pin
Heath Stewart26-Jul-04 18:50
protectorHeath Stewart26-Jul-04 18:50 
GeneralRe: Binding DataView to MSChart Pin
Kuan Wai Mun2-Aug-04 17:36
Kuan Wai Mun2-Aug-04 17:36 
GeneralScrollBars for DataGrid Pin
Khang Nguyen26-Jul-04 14:43
Khang Nguyen26-Jul-04 14:43 
GeneralRe: ScrollBars for DataGrid Pin
DougW4826-Jul-04 15:33
DougW4826-Jul-04 15:33 
GeneralRe: ScrollBars for DataGrid Pin
Khang Nguyen27-Jul-04 6:11
Khang Nguyen27-Jul-04 6:11 
Generalproblems by &quot;add web reference&quot; in https Pin
Stephan Wright26-Jul-04 12:42
Stephan Wright26-Jul-04 12:42 
GeneralRe: problems by &quot;add web reference&quot; in https Pin
Heath Stewart27-Jul-04 11:04
protectorHeath Stewart27-Jul-04 11:04 
GeneralRe: problems by &quot;add web reference&quot; in https Pin
Stephan Wright27-Jul-04 22:12
Stephan Wright27-Jul-04 22:12 
GeneralRe: problems by &quot;add web reference&quot; in https Pin
Heath Stewart28-Jul-04 4:16
protectorHeath Stewart28-Jul-04 4:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.