Home

GDI+ Examples: 2-Column Chart

 
Company Sales Annual Report

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. Set the form's Icon to Drive:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Graphics\icons\Office\GRAPH08.ICO
  3. 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   This Year's Sales  
    Label Label   Last Year's Sales  
  4. Double-click an unoccupied area on the form and implement its Load event as follows:
     
    #pragma once
    
    
    namespace WeeklySales1
    {
    
    
    	private:
    		/// <summary>
    		/// Required designer variable.
    		/// </summary>
    		System::ComponentModel::Container * components;
    		Graphics *graphDrawingArea;
    		Bitmap   *bmpDrawingArea;
    
    		/// <summary>
    		/// Required method for Designer support - do not modify
    		/// the contents of this method with the code editor.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			
    			. . . No Change
    
    		}	
    	private: System::Void Form1_Load(System::Object *  sender, System::EventArgs *  e)
    		{
    			 bmpDrawingArea   = new Bitmap(Width, Height);
    			 graphDrawingArea = Graphics::FromImage(bmpDrawingArea);
    		}
    
    };
    }
  5. Return to the form and click an empty area on it. In the Properties window, click the Events button Events
  6. Double-click the Paint field and implement its event as follows:
     
    private: System::Void Form1_Paint(System::Object *  sender, System::Windows::Forms::PaintEventArgs *  e)
    		 {
    			 e->Graphics->DrawImage(bmpDrawingArea, 0, 0);
    		 }
  7. Double-click the Generate button and implement its Click event as follows:
     
    private: 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 = this->txtCurrentQtr1->Text->ToInt32(0) / 100;
    	 int curQtr2 = this->txtCurrentQtr2->Text->ToInt32(0) / 100;
    	 int curQtr3 = this->txtCurrentQtr3->Text->ToInt32(0) / 100;
    	 int curQtr4 = this->txtCurrentQtr4->Text->ToInt32(0) / 100;
    
    			 // Create an array of Rectangle objects for the current year
    	 Rectangle rectCurrentYear[] = { 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 = this->txtPreviousQtr1->Text->ToInt32(0) / 100;
    	 int prvQtr2 = this->txtPreviousQtr2->Text->ToInt32(0) / 100;
    	 int prvQtr3 = this->txtPreviousQtr3->Text->ToInt32(0) / 100;
    	 int prvQtr4 = this->txtPreviousQtr4->Text->ToInt32(0) / 100;
    
    	 // Create an array of Rectangle objects for the previous year
    	 Rectangle rectPreviousYear[] = { 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  = new HatchBrush(HatchStyle::DiagonalCross, Color::White, Color::Blue);
    	 HatchBrush *brushDotDiamond = new 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(new Pen(Color::Blue), rectPreviousYear);
    	 // Draw the chart for the current year in front
    	 graphDrawingArea->FillRectangles(brushDotDiamond, rectCurrentYear);
    	 graphDrawingArea->DrawRectangles(new 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(new 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(new Pen(Color::Blue), this->lblLastYear->Left-30, this->lblLastYear->Top, 20, 14);
    
    	 graphDrawingArea->DrawRectangle(new Pen(Color::Black), 25, 350, Width - 220, 1);
    	 Invalidate();
    }
  8. Return to the form. Double-click the Close button and implement its Click event as follows:
     
    private: System::Void btnClose_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 Close();
    }
  9. Execute the application and test the form
     
     
  10. 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:
     
    private: 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 = this->txtCurrentQtr1->Text->ToInt32(0) / 100;
    	 int curQtr2 = this->txtCurrentQtr2->Text->ToInt32(0) / 100;
    	 int curQtr3 = this->txtCurrentQtr3->Text->ToInt32(0) / 100;
    	 int curQtr4 = this->txtCurrentQtr4->Text->ToInt32(0) / 100;
    
    	 // Create an array of Rectangle objects for the current year
    	 Rectangle rectCurrentYear[] = { 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 = this->txtPreviousQtr1->Text->ToInt32(0) / 100;
    	 int prvQtr2 = this->txtPreviousQtr2->Text->ToInt32(0) / 100;
    	 int prvQtr3 = this->txtPreviousQtr3->Text->ToInt32(0) / 100;
    	 int prvQtr4 = this->txtPreviousQtr4->Text->ToInt32(0) / 100;
    
    	 // Create an array of Rectangle objects for the previous year
    	 Rectangle rectPreviousYear[] = { 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, 300, 175);
    	 LinearGradientBrush *linGradBrush = new LinearGradientBrush(rect,
    				 Color::FromArgb(204, 102, 0),
    				 Color::AntiqueWhite,
    				 LinearGradientMode::Vertical);
    	 graphDrawingArea->FillRectangle(linGradBrush, rect);
    	 graphDrawingArea->DrawRectangle(new Pen(Color::Black), rect);
    
    	 HatchBrush *brushDiagCross  = new HatchBrush(HatchStyle::DiagonalCross, Color::White, Color::Blue);
    	 HatchBrush *brushDotDiamond = new 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(new Pen(Color::Blue), rectPreviousYear);
    	 // Draw the chart for the current year in front
    	 graphDrawingArea->FillRectangles(brushDotDiamond, rectCurrentYear);
    	 graphDrawingArea->DrawRectangles(new 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(new 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(new Pen(Color::Blue), this->lblLastYear->Left-30, this->lblLastYear->Top, 20, 14);
    
    	 graphDrawingArea->DrawRectangle(new Pen(Color::Black), 25, 350, Width - 220, 1);
    	 Invalidate();
    }
  2. Execute the application to test it:
     
    Company Sales Annual Report
  3. After using the form, close it
 

Home Copyright © 2004-2010 FunctionX, Inc.