Home

GDI+ Examples: 2-Column Chart

 

Introduction

In our introduction to charts, we used rectangles to draw a column chart. We will continue with the same approach here. This time, we will create a 2-column chart. This type of chart is used to analyze numbers that each represents the same category of information but from two periods.

 

Practical LearningPractical Learning: Creating the Chart

  1. Start a new Windows Forms Application named YearlySales
  2. Design the form as follows:
     
     
    Control Name Text Other Properties
    GroupBox GroupBox   Current Year's Sales  
    Label Label   1st Qtr  
    Label Label   2nd Qtr  
    Label Label   3rd Qtr  
    Label Label   4th Qtr  
    TextBox TextBox txtCurrentQtr1 1200  
    TextBox TextBox txtCurrentQtr2 14500 TextAlign: Right
    TextBox TextBox txtCurrentQtr3 8500 TextAlign: Right
    TextBox TextBox txtCurrentQtr4 16800 TextAlign: Right
    Button Button Close btnClose  
    GroupBox GroupBox   Previous Year's Sales  
    Label Label   1st Qtr  
    Label Label   2nd Qtr  
    Label Label   3rd Qtr  
    Label Label   4th Qtr  
    TextBox TextBox txtPreviousQtr1 10000  
    TextBox TextBox txtPreviousQtr2 11000 TextAlign: Right
    TextBox TextBox txtPreviousQtr3 12500 TextAlign: Right
    TextBox TextBox txtPreviousQtr4 15800 TextAlign: Right
    Button Button Generate btnGenerate  
    Label Label   _________ Legend _________  
    Label Label lblCurYear This Year's Sales  
    Label Label lblLastYear Last Year's Sales  
  3. Right-click the form and click View Code and declare the following two variables:
     
    private:
    	/// <summary>
    	/// Required designer variable.
    	/// </summary>
    	System::ComponentModel::Container ^components;
    	Graphics ^ graphDrawingArea;
    	Bitmap   ^ bmpDrawingArea;
  4. Return to the form
  5. Double-click an unoccupied area on the form and implement its Load event as follows:
     
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
    	 bmpDrawingArea   = gcnew Bitmap(Width, Height);
    	 graphDrawingArea = Graphics::FromImage(bmpDrawingArea);
    }
  6. Return to the form and click an empty area on it. In the Properties window, click the Events button Events
  7. Double-click the Paint field and implement its event as follows:
     
    System::Void Form1_Paint(System::Object^  sender, 
    	System::Windows::Forms::PaintEventArgs^  e)
    {
    	 e->Graphics->DrawImage(bmpDrawingArea, 0, 0);
    }
  8. Return to the form
  9. Double-click the Generate button and implement its Click event as follows:
     
    System::Void btnGenerate_Click(System::Object^  sender, 
    				System::EventArgs^  e)
    {
        using namespace System::Drawing::Drawing2D;
    
        // Retrieve the values of the current year's sales
        int curQtr1 = int::Parse(this->txtCurrentQtr1->Text) / 100;
        int curQtr2 = int::Parse(this->txtCurrentQtr2->Text) / 100;
        int curQtr3 = int::Parse(this->txtCurrentQtr3->Text) / 100;
        int curQtr4 = int::Parse(this->txtCurrentQtr4->Text) / 100;
    
        // Create an array of Rectangle objects for the current year
        array<Rectangle> ^ rectCurrentYear = gcnew array<Rectangle>(4)
        {
    	Rectangle(this->txtCurrentQtr1->Left+20,
    		  350-curQtr1, 40, curQtr1),
    	Rectangle(this->txtCurrentQtr2->Left+20,
    		  350-curQtr2, 40, curQtr2),
    	Rectangle(this->txtCurrentQtr3->Left+20,
    		  350-curQtr3, 40, curQtr3),
    	Rectangle(this->txtCurrentQtr4->Left+20,
    		  350-curQtr4, 40, curQtr4) };
    
    	 // Retrieve the values of last year's sales
    	 int prvQtr1 = int::Parse(this->txtPreviousQtr1->Text) / 100;
    	 int prvQtr2 = int::Parse(this->txtPreviousQtr2->Text) / 100;
    	 int prvQtr3 = int::Parse(this->txtPreviousQtr3->Text) / 100;
    	 int prvQtr4 = int::Parse(this->txtPreviousQtr4->Text) / 100;
    
    	 // Create an array of Rectangle objects for the previous year
    	 array<Rectangle> ^ rectPreviousYear = 
    		gcnew array<Rectangle>(4)
    	 {
    	     Rectangle(this->txtPreviousQtr1->Left+30,
    		       350-prvQtr1, 40, prvQtr1),
     	     Rectangle(this->txtPreviousQtr2->Left+30,
    		       350-prvQtr2, 40, prvQtr2),
    	     Rectangle(this->txtPreviousQtr3->Left+30,
    		       350-prvQtr3, 40, prvQtr3),
    	     Rectangle(this->txtPreviousQtr4->Left+30,
    		       350-prvQtr4, 40, prvQtr4)
    	 };
    
    // In case the user has changed the values, erase the previous chart
    	 graphDrawingArea->Clear(this->BackColor);
    
    	 HatchBrush ^ brushDiagCross  = 
    			gcnew HatchBrush(HatchStyle::DiagonalCross,
    			Color::White, Color::Blue);
    	 HatchBrush ^ brushDotDiamond = 
    			gcnew HatchBrush(HatchStyle::DottedDiamond, 
    			Color::Fuchsia, Color::Brown);
    
    	 // Draw the chart for the previous year first to send it back
    	 graphDrawingArea->FillRectangles(brushDiagCross,
    					  rectPreviousYear);
    	 graphDrawingArea->DrawRectangles(gcnew Pen(Color::Blue),
    					  rectPreviousYear);
    	 // Draw the chart for the current year in front
    	 graphDrawingArea->FillRectangles(brushDotDiamond,
    					  rectCurrentYear);
    	 graphDrawingArea->DrawRectangles(gcnew Pen(Color::Red),
    					  rectCurrentYear);
    
    	 // Draw the small rectangles of the legend
    	 graphDrawingArea->FillRectangle(brushDotDiamond,
    					 this->lblCurYear->Left-30,
    					 this->lblCurYear->Top,  20, 14);
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Red),
    					 this->lblCurYear->Left-30,
    					 this->lblCurYear->Top,  20, 14);
    	 graphDrawingArea->FillRectangle(brushDiagCross,
    					 this->lblLastYear->Left-30,
    					 this->lblLastYear->Top, 20, 14);
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Blue),
    					 this->lblLastYear->Left-30,
    					 this->lblLastYear->Top, 20, 14);
    
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Black), 25,
    					 350, Width - 220, 1);
    	 Invalidate();
    }
  10. Return to the form. Double-click the Close button and implement its Click event as follows:
     
    System::Void btnClose_Click(System::Object^  sender, System::EventArgs^  e)
    {
    	 Close();
    }
  11. Execute the application and test the form
     
     
  12. After using it, close the form

The Chart's Background

One of the improvements you can bring to a chart is to provide it with a fancy background. This also can be a shape you draw. You can then paint it using one of the brushes of the GDI+ library.

 

Practical LearningPractical Learning: Painting the Background

  1. Change the Click event of the Generate button as follows:
     
    System::Void btnGenerate_Click(System::Object^  sender, 
    				System::EventArgs^ e)
    {
        using namespace System::Drawing::Drawing2D;
    
        // Retrieve the values of the current year's sales
        int curQtr1 = int::Parse(this->txtCurrentQtr1->Text) / 100;
        int curQtr2 = int::Parse(this->txtCurrentQtr2->Text) / 100;
        int curQtr3 = int::Parse(this->txtCurrentQtr3->Text) / 100;
        int curQtr4 = int::Parse(this->txtCurrentQtr4->Text) / 100;
    
        // Create an array of Rectangle objects for the current year
        array<Rectangle> ^ rectCurrentYear = gcnew array<Rectangle>(4)
        {
    	Rectangle(this->txtCurrentQtr1->Left+20,
    		  350-curQtr1, 40, curQtr1),
    	Rectangle(this->txtCurrentQtr2->Left+20,
    		  350-curQtr2, 40, curQtr2),
    	Rectangle(this->txtCurrentQtr3->Left+20,
    		  350-curQtr3, 40, curQtr3),
    	Rectangle(this->txtCurrentQtr4->Left+20,
    		  350-curQtr4, 40, curQtr4) };
    
    	 // Retrieve the values of last year's sales
    	 int prvQtr1 = int::Parse(this->txtPreviousQtr1->Text) / 100;
    	 int prvQtr2 = int::Parse(this->txtPreviousQtr2->Text) / 100;
    	 int prvQtr3 = int::Parse(this->txtPreviousQtr3->Text) / 100;
    	 int prvQtr4 = int::Parse(this->txtPreviousQtr4->Text) / 100;
    
    	 // Create an array of Rectangle objects for the previous year
    	 array<Rectangle> ^ rectPreviousYear = 
    		gcnew array<Rectangle>(4)
    	 {
    	     Rectangle(this->txtPreviousQtr1->Left+30,
    		       350-prvQtr1, 40, prvQtr1),
     	     Rectangle(this->txtPreviousQtr2->Left+30,
    		       350-prvQtr2, 40, prvQtr2),
    	     Rectangle(this->txtPreviousQtr3->Left+30,
    		       350-prvQtr3, 40, prvQtr3),
    	     Rectangle(this->txtPreviousQtr4->Left+30,
    		       350-prvQtr4, 40, prvQtr4)
    	 };
    
       // In case the user has changed the values, erase the previous chart
    	 graphDrawingArea->Clear(this->BackColor);
    
    	 Rectangle rect(20, 175, 320, 175);
        LinearGradientBrush ^ linGradBrush = gcnew LinearGradientBrush(rect,
    				 Color::FromArgb(204, 102, 0),
    				 Color::AntiqueWhite,
    				 LinearGradientMode::Vertical);
    	 graphDrawingArea->FillRectangle(linGradBrush, rect);
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Black), rect);
    
    	 HatchBrush ^ brushDiagCross  = 
    			gcnew HatchBrush(HatchStyle::DiagonalCross,
    			Color::White, Color::Blue);
    	 HatchBrush ^ brushDotDiamond = 
    			gcnew HatchBrush(HatchStyle::DottedDiamond, 
    			Color::Fuchsia, Color::Brown);
    
    	 // Draw the chart for the previous year first to send it back
    	 graphDrawingArea->FillRectangles(brushDiagCross,
    					  rectPreviousYear);
    	 graphDrawingArea->DrawRectangles(gcnew Pen(Color::Blue),
    					  rectPreviousYear);
    	 // Draw the chart for the current year in front
    	 graphDrawingArea->FillRectangles(brushDotDiamond,
    					  rectCurrentYear);
    	 graphDrawingArea->DrawRectangles(gcnew Pen(Color::Red),
    					  rectCurrentYear);
    
    	 // Draw the small rectangles of the legend
    	 graphDrawingArea->FillRectangle(brushDotDiamond,
    					 this->lblCurYear->Left-30,
    					 this->lblCurYear->Top,  20, 14);
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Red),
    					 this->lblCurYear->Left-30,
    					 this->lblCurYear->Top,  20, 14);
    	 graphDrawingArea->FillRectangle(brushDiagCross,
    					 this->lblLastYear->Left-30,
    					 this->lblLastYear->Top, 20, 14);
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Blue),
    					 this->lblLastYear->Left-30,
    					 this->lblLastYear->Top, 20, 14);
    
    	 graphDrawingArea->DrawRectangle(gcnew Pen(Color::Black), 25,
    					 350, Width - 220, 1);
    	 Invalidate();
    }
  2. Execute the application to test it:
     
  3. After using the form, close it

 

 
 

Home Copyright © 2004-2010 FunctionX, Inc.