Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Charts for Windows Application using C#

0.00/5 (No votes)
7 Apr 2009 2  
Create charts using inbuilt functions of .NET Framework in window application and C#

Introduction

Drawing charts or graphs is a very common requirement for many projects. If you have been working as a software professional, you must have come across the situation of drawing charts. Most of the time, we tend to rely on third party controls which are costly.

Background

I am going to demonstrate .NET’s in-built function to draw some basic charts. At the end of the article, you should be able to draw basic charts in your Windows application. I am using C# here.

Using the Code

I created a Windows application and wrote the following four functions to handle four different types of charts.

Charts

  1. DrawSliceChart 
  2. DrawPieChart
  3. DrawBarChart
  4. DrawLineChart

For our example, we will take input weight as (13, 23, 33, 15, 20, 10, 4, 11). We will pass this array to all of the above functions. Let us discuss all the functions one by one.

DrawSliceChart

Consider it as cutting a cake into slices based on the weight. In this chart, angle of slice is linearly proportional to weight. To understand this, we will discuss the FillPie function supported by .NET.

Signature of FillPie is as follows:

Void FillPie(Brush brush, int x,int y, int width,int height,
				int startAngle, int sweepAngle)

This function is used to fill as ellipse if sweep angle is 360. To make it a circle, we make height and width both equal to diameter of circle.

height = width = 2*radius;

Let us look into the details of parameters.

  • Brush brush: It is a brush object used to fill the Pie.

  • Int x: x co-ordinate of upper left corner of the bounding rectangle that defines the ellipse from which the pie section comes. So if the x co-ordinate of center of our circle is x0 and radius is r:

    x = x0 – r;
  • Int y: Similar to x.

    y = y0 – r;
  • Int width: width of bounding rectangle that defines the ellipse from which the pie section comes.

    width = 2*radius;
  • Int startAngle: Angle in degrees measured clockwise from the x-axis to the first side of the pie section. So we start with 0 degrees and increment it with the sweepAngle for the next slice to start right after the end of previous slice.

  • Int sweepAngle: Angle in degrees measured clockwise from the startAngle parameter to the second side of pie section. So this is span of angle based on weight. So 360 degrees is proportionally divided into 8 parts based on the weight.

    For weight 23 in our example:

    Int totalWeight = 13+23+33+15+20+10+4+11;
    	sweepAngle = (23 * 360)/totalWeight;

Then I use another function to draw the border around the shape: DrawPie. The only difference between this and FillPie is that it takes Pen object instead of Brush.

private void DrawSliceChart(PaintEventArgs e, int[] alWeight)
{
    int numberOfSections = alWeight.Length
    int x0 = 100;
    int y0 = 100;
    int radius = 100;
    int startAngle = 0;
    int sweepAngle = 0;
    int[] height = new int[numberOfSections];
    int total = SumOfArray(alWeight);
    Random rnd = new Random();
    SolidBrush brush = new SolidBrush(Color.Aquamarine);
    Pen pen = new Pen(Color.Black);
    for (int i = 0; i < numberOfSections; i++)
    {
        brush.Color = Color.FromArgb(rnd.Next(200, 255),
			rnd.Next(255), rnd.Next(255), rnd.Next(255));
        // Since we have taken integer so last slice needs to
        // be rounded off to fit into the remaining part.
        if (i == numberOfSections - 1)
            sweepAngle = 360 - startAngle;
        else
            sweepAngle = (360 * alWeight[i]) / total;
        e.Graphics.FillPie(brush, x0 - height[i], y0 - height[i],
			2*radius, 2*radius, startAngle , sweepAngle);
        e.Graphics.DrawPie(pen, x0 - height[i], y0 - height[i],
			2*radius, 2*radius, startAngle, sweepAngle);
        startAngle += sweepAngle;
        brush.Color = Color.FromKnownColor(KnownColor.Black);
    }
} 

DrawPieChart

This is another chart which also uses the same in built function with little modification in the previous code. In this chart, angle of slice remains the same for all slices but the radius varies based on the weight.

So here we will first find out maximum weight MaxWeight. Then MaxWeight will be equal to the radius and other slices will have radius proportionally lesser then MaxWeight.

e.g. for weight 23:

MaxWeight = 33;
	width = (23*radius)/MaxWeight;
	sweepAngle = 360/TotalNumberOfWeights; 

startAngle will start from 0 and is incremented by sweepAngle.

startAngle += sweepAngle; 
private void DrawPieChart(PaintEventArgs e, int[] alWeight)
        {
            int numberOfSections = alWeight.Length;
            int x0 = 600;
            int y0 = 500;
            int radius = 200;
            int startAngle = 0;
            int sweepAngle = 360/numberOfSections;
            int[] height = new int[numberOfSections];
            int maxWeight = MaxValue(alWeight);
            Random rnd = new Random(10);
            SolidBrush brush = new SolidBrush(Color.Aquamarine);
            Pen pen = new Pen(Color.Black);
            for(int i =0;i<numberofsections;i++){
                height[i] = ((Convert.ToInt32(alWeight[i])) * radius) / maxWeight;
                brush.Color = Color.FromArgb(rnd.Next(200, 255), rnd.Next(255),
                    rnd.Next(255), rnd.Next(255));
                e.Graphics.FillPie
		  (brush, x0 - height[i], y0 - height[i], 2 * height[i],
                    2 * height[i],(startAngle+i*45), sweepAngle);
                e.Graphics.DrawPie(pen, x0 - height[i], y0 - height[i], 2 * height[i],
                    2 * height[i], (startAngle + i * 45), sweepAngle);
                //e.Graphics.FillPie(Brushes.Blue, x0 - height[i], y0 - height[i],
                //2 * height[i], 2 * height[i], (startAngle + i * 45 -2), 2);
            }
        }

DrawBarChart

In this, we make use of ‘DrawRectangle’ in built function. The idea here is to first create a big rectangle defining the boundary of bar graphs. DrawRectangle takes the following parameters:

  1. Pen – This defines the color and style of border
  2. Rectangle Rectangle object to be created

We will look into the rectangle object.

Rectangle(int x, int y, int width,int height) 

X and y are the co-ordinates of top left corner of rectangle.

Width and height are width and height of rectangle.

So to draw a bar, we will use the same function. The only thing we have to identify is these four parameters of Rectangle. Width is constant and is equal to total length of outer rectangle divided by total number of bars. Height is calculated as follows:

Height = (weight of current array element *
		height of outer rectangle )/ maximum weight. 

X coordinate is incremented by width of bars everytime a new bar is created.

Y co-ordinate is calculated by the following formula:

y = y coordinate of outer rectangle + height of outer rectangle –
			height of bar calculated using above formula 

Like DrawPie and DrawSlice, we fill the shape with the corresponding fill function.

private void DrawBarChart(PaintEventArgs e, int[] alWeight)
        {
            int numberOfSections = alWeight.Length;
            int lengthArea = 400;
            int heightArea = 250;
            int topX = 400;
            int topY = 20;
            int maxWeight = MaxValue(alWeight);
            int[] height = new int[numberOfSections];
            int total = SumOfArray(alWeight);
            Random rnd = new Random();
            SolidBrush brush = new SolidBrush(Color.Aquamarine);
            Pen pen = new Pen(Color.Gray);
            Rectangle rec = new Rectangle(topX,topY,lengthArea,heightArea);
            e.Graphics.DrawRectangle(pen,rec);
            pen.Color = Color.Black;
            int smallX = topX;
            int smallY = 0;
            int smallLength = (lengthArea/alWeight.Length);
            int smallHeight = 0;
            for (int i = 0; i < numberOfSections; i++)
            {
                 brush.Color = Color.FromArgb(rnd.Next(200, 255),
			rnd.Next(255), rnd.Next(255), rnd.Next(255));
                 smallHeight = ((alWeight[i] * heightArea )/ maxWeight);
                 smallY = topY + heightArea - smallHeight;
                 Rectangle rectangle = new Rectangle
			(smallX, smallY, smallLength, smallHeight);
                 e.Graphics.DrawRectangle(pen,rectangle);
                 e.Graphics.FillRectangle(brush, rectangle);
                 brush.Color = Color.FromKnownColor(KnownColor.Black);
                 e.Graphics.DrawRectangle(pen, rectangle);
                 smallX = smallX + smallLength;
             }
        }

DrawLineChart

To draw a line chart, we first create boundary with ‘DrawRectangle’ in built function. Then we decide on the points to draw the line.

X coordinate is incremented by equal distance and y co-ordinate is set based on the weight.

Here, to highlight each point, I am using function DrawDots to highlight the point by making a circle of radius 5.

private void DrawLineChart(PaintEventArgs e,int[] alWeight)
{
    int numberOfSections = alWeight.Length;
    int lengthArea = 400;
    int heightArea = 250;
    int topX = 20;
    int topY = 400;
    int maxWeight = MaxValue(alWeight);
    int[] height = new int[numberOfSections];
    int total = SumOfArray(alWeight);
    Random rnd = new Random();
    SolidBrush brush = new SolidBrush(Color.Aquamarine);
    Pen pen = new Pen(Color.Gray);
    Rectangle rec = new Rectangle(topX, topY, lengthArea, heightArea);
    e.Graphics.DrawRectangle(pen, rec);
    pen.Color = Color.Black;
    int smallX = topX;
    int smallY = 0;
    int smallLength = (lengthArea / (alWeight.Length + 1));
    int smallHeight = 0;
    Point p1 = new Point();
    Point p2 = new Point();
    for (int i = 0; i < numberOfSections; i++)
    {
        brush.Color = Color.FromArgb(rnd.Next(200, 255),
		rnd.Next(255), rnd.Next(255), rnd.Next(255));
        p1 = p2;
        p2.X = p2.X + smallLength;
        smallHeight = ((alWeight[i] * heightArea) / maxWeight);
        p2.Y = topY + heightArea - smallHeight;
        if (p1.X != 0 && p1.Y != 0)
        {
            e.Graphics.DrawLine(pen, p1, p2);
        }
        DrawDots(e,p2);
        smallX = smallX + smallLength;
    }
}

Here is the function to highlight the point:

private void DrawDots(PaintEventArgs e, Point p1)
{
    Pen pen = new Pen(Color.SeaGreen);
    e.Graphics.DrawPie(pen, p1.X-5 , p1.Y-5, 10, 10, 0, 360);
    e.Graphics.FillPie(new SolidBrush(Color.Purple),
			p1.X - 5, p1.Y - 5, 10, 10, 0, 360);
}

Points of Interest

So these are few of the charts that we can create. We can also customize them based on our requirement. If your requirement is simply to draw one chart similar to any of these three, just copy paste the function and change the co-ordinate and color as per your requirement. In addition to that, I have used 2 more simple functions to get maximum and total of array. You can find the complete source code attached.

The important thing to note is that all the four functions are called from Paint event handler function and takes PaintEventArgs and array of weights as parameters.

History

  • 7th April, 2009: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here