Drawing on a Form

A Geekpedia page gives a useful introduction to drawing on a form. We have adapted our existing Pascal drawing code and provide here a C# version that compiles in SharpDevelop. Plasmoid.Extensions is needed here only for the rounded rectangle. The linked page is very informative.

The form is divided into cells with a horizontal border HB and vertical border VB. CellInnerWidth and CellInnerHeight are the cell dimensions within these borders. The final cell contains a rectangle drawn on a translated, rotated and scaled canvas. The code follows a screenshot of the output.

Output

Output

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Plasmoid.Extensions;

namespace DrawDemo
{
  public partial class MainForm: Form
  {
    private Graphics g;
    private Pen pen1 = new Pen(Color.Red);
    private const int HB = 10;     // Horizontal border
    private const int VB = 10;     // Vertical border
    private int Count, MaxX, MaxY, Col1, Col2, Col3, Row1, Row2, Row3,  X, Y, CentreX, CentreY, CellInnerWidth, CellInnerHeight, Radius;
  
    private Point[] PentagonPoints = new Point[6];
    private Point[] TrianglePoints = new Point[4];
 
    protected override void OnPaint(PaintEventArgs pea) 
    {
      g = pea.Graphics;
      RenderRow1();
      RenderRow2();
      RenderRow3();
      RenderRow4();
    }
 
    public void RenderRow1()
    {
      // Red rect
      g.DrawRectangle(Pens.Red, HB, VB, CellInnerWidth, CellInnerHeight);
      // Yellow filled rectangle 
      g.FillRectangle(Brushes.Yellow, Col1 + HB, VB, CellInnerWidth, CellInnerHeight);
      // Green circle needs bounding square
      CentreX = (Col2 + Col3) / 2;
      CentreY = Row1 / 2;
      g.DrawEllipse(Pens.Green, CentreX - Radius, CentreY - Radius, 2 * Radius, 2 * Radius);
      // Blue filled ellipse needs bounding rectangle
      g.FillEllipse(Brushes.Blue, Col3 + HB, VB, CellInnerWidth, CellInnerHeight);     
    }
    
    public void RenderRow2()
    {
      // Aqua line (solid)
      pen1.Color = Color.Aqua;
      pen1.Width = 4;
      g.DrawLine(pen1, HB, Row1 + VB, Col1 - HB, Row2 - VB);
      // Teal dashed line
      pen1.Width = 3;
      pen1.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
      pen1.Color = Color.Teal;
      g.DrawLine(pen1, Col1 + HB, Row2 - VB, Col2 - HB, Row1 + VB);
      pen1.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
      // White ellipse with dark grey outline
      pen1.Color = Color.DarkGray;
      pen1.Width = 2;
      g.DrawEllipse(pen1, Col2 + HB, Row1 + VB, CellInnerWidth, CellInnerHeight);
      g.FillEllipse(Brushes.White, Col2 + HB + 2, Row1 + VB + 2, CellInnerWidth - 4, CellInnerHeight - 4); 
      // Purple filled circle
      CentreX = (Col3 + MaxX) / 2;
      CentreY = (Row1 + Row2) / 2;
      g.FillEllipse(Brushes.Purple, CentreX - Radius, CentreY - Radius,  2 * Radius, 2 * Radius);         
    }
    public void RenderRow3()
    {
      // Three quarters of lime ellipse
      CentreX = Col1 / 2;
      CentreY = (Row3 + Row2) / 2;       
      g.FillPie(Brushes.Lime, CentreX - Radius, CentreY - Radius, 2 * Radius, 2 * Radius, 0, 270);
      // Dark grey rounded rectangle needs Plasmoid.Extensions 
      // http://www.codeproject.com/Articles/38436/Extended-Graphics-Rounded-rectangles-Font-metrics
      g.FillRoundedRectangle(Brushes.DarkGray, Col1 + 2 * HB, Row2 + VB, CellInnerWidth, CellInnerHeight, 20);
      // Fuchsia pentagon
      PentagonPoints[0] = new Point((Col3 + Col2) / 2,Row2 + VB);
      PentagonPoints[1] = new Point(Col3 - HB,(Row2 + Row3) / 2);
      PentagonPoints[2] = new Point(Col3 - (Col1 / 3), Row3 - VB);
      PentagonPoints[3] = new Point(Col2 + (Col1 / 3), Row3 - VB);
      PentagonPoints[4] = new Point(Col2 +  HB,(Row2 + Row3) / 2);
      PentagonPoints[5] =  PentagonPoints[0];
      g.DrawLines(Pens.Fuchsia, PentagonPoints);
      // Red filled triangle
      TrianglePoints[0] = new Point((Col3 + MaxX) / 2, Row2 + VB);
      TrianglePoints[1] = new Point(MaxX - HB, Row3 - VB);
      TrianglePoints[2] = new Point(Col3 + HB, Row3 - VB);
      TrianglePoints[3] = TrianglePoints[0];
      g.FillPolygon(Brushes.Red, TrianglePoints);
   } 

    public void RenderRow4()
    {
      // Navy arc of ellipse
      g.DrawArc(Pens.Navy, HB, Row3 + VB, CellInnerWidth, CellInnerHeight, 0, 270);
      // Blue text   
      g.DrawString("pp4s.co.uk", new Font("Arial", 16, FontStyle.Bold), Brushes.Blue, Col1 + HB, (Row3 + MaxY) / 2);
      // Maroon curve
      Count = 0;
      X = Col2 + HB;
      Y = Row3 + VB;
      while ( (X <= Col3) && (Y <= MaxY)) 
      {
        g.FillRectangle(Brushes.Maroon, X - 1, Y - 1, 2, 2);
        Count += 1;
        X = Col2 + HB + (Count * MaxX ) / 40;
        Y = Row3 + VB + (Count * Count * MaxY) / 150;
      }
      // Apply translation, rotation and scale to the canvas then draw a green rectangle
      g.TranslateTransform((Col3 + MaxX) / 2, (Row3 + MaxY) / 2);
      g.RotateTransform(25);
      g.ScaleTransform(0.8F, 0.8F);
      g.FillRectangle(Brushes.DarkGreen, -CellInnerWidth / 2, -CellInnerHeight / 2, CellInnerWidth, CellInnerHeight);
   } 
        
    public MainForm()
    {
      InitializeComponent();
      Width = 500;
      Height = 400;
      Col1 = ClientSize.Width / 4;   //End of column
      Col2 = ClientSize.Width / 2;
      Col3 = Col1 + Col2;
      Row1 = ClientSize.Height / 4;   //End of row
      Row2 = ClientSize.Height / 2;
      Row3 = Row1 + Row2;
      MaxX = ClientSize.Width;
      MaxY = ClientSize.Height;
      CellInnerWidth = Col1 - 2 * HB;
      CellInnerHeight = Row1 - 2 * VB;
      if (CellInnerWidth < CellInnerHeight)
        Radius = CellInnerWidth / 2;
      else
        Radius = CellInnerHeight / 2;
    }
  }
}

Programming - a skill for life!

C# Demonstrations of I/O, arrays, methods, classes, loops, enums, pointers, file handling, Firebird databases, LINQ and drawing on a form