Lesson 26 · Graphics & GDI+

Graphics & GDI+ Drawing

Master VB 2026's drawing engine — the Graphics object, Pen and Brush, lines, rectangles, ellipses, text, polygons, pie charts, gradients, and animated graphics with the Timer control.

Key Takeaway: All GDI+ drawing happens inside the Paint event through a Graphics object. The coordinate origin (0, 0) is the top-left corner; X increases right, Y increases down. Always wrap Pen and Brush objects in Using blocks so they are disposed immediately after use. Call picBox.Invalidate() to trigger a repaint — never store the Graphics object; get a fresh one from the Paint event each time.
Graphics
Drawing surface
Obtained from e.Graphics in Paint event. All draw calls go here.
Pen
Outlines / lines
Color + width. New Pen(Color.Red, 2). Use Using block to dispose.
SolidBrush
Filled shapes
FillRectangle, FillEllipse, FillPolygon. New SolidBrush(Color.Blue).
LinearGradientBrush
Gradient fill
Smooth colour transition from point1 to point2.
DrawLine
Method
g.DrawLine(pen, x1, y1, x2, y2) — straight line between two points.
DrawRectangle / FillRectangle
Method
Outline or fill a rectangle defined by x, y, width, height.
DrawEllipse / FillEllipse
Method
Draws an ellipse (or circle) inside its bounding rectangle.
DrawString
Method
Render text at a point or inside a rectangle using a Font object.
DrawPolygon / FillPolygon
Method
Pass a Point() array. VB automatically closes the last edge.
DrawPie / FillPie
Method
Slice of an ellipse. startAngle and sweepAngle in degrees.
Invalidate()
Method
Marks the control dirty → triggers Paint on next UI cycle.
SmoothingMode
Property
g.SmoothingMode = AntiAlias — removes jagged edges on curves.

26.1 The Graphics Object & Paint Event

GDI+ drawing always happens in response to the Paint event. The event argument e.Graphics provides the drawing surface. Every time the window is resized, uncovered, or Invalidate() is called, the Paint event fires and you redraw from scratch.

GraphicsIntro.vb — Visual Basic 2026
' --- Drawing on a PictureBox ---
Private Sub picBox_Paint(sender As Object, e As PaintEventArgs) Handles picBox.Paint
    Dim g As Graphics = e.Graphics
    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias   ' smooth curves

    ' Draw a red line
    Using pen As New Pen(Color.Red, 2)
        g.DrawLine(pen, 10, 10, 200, 10)
    End Using

    ' Fill a blue rectangle
    Using brush As New SolidBrush(Color.SteelBlue)
        g.FillRectangle(brush, 10, 30, 120, 60)
    End Using

    ' Draw a green circle (ellipse in square bounding box)
    Using pen As New Pen(Color.Green, 3)
        g.DrawEllipse(pen, 150, 30, 60, 60)
    End Using
End Sub

' --- Drawing on the Form itself ---
Private Sub Form1_Paint(...) Handles MyBase.Paint
    Dim g = e.Graphics
    ' draws directly on the form surface
End Sub

' --- Trigger a repaint (e.g. from a button click) ---
Private Sub btnDraw_Click(...) Handles btnDraw.Click
    picBox.Invalidate()   ' schedules Paint; does NOT draw immediately
End Sub

' --- WRONG — never store the Graphics object ---
' Dim g As Graphics = picBox.CreateGraphics()   ← erased on repaint!
' Use Invalidate() + Paint event instead.

' --- Clear the canvas ---
g.Clear(Color.White)   ' fill entire surface with White
Coordinate System

The origin (0, 0) is the top-left corner. X increases to the right; Y increases downward. A rectangle at (10, 30, 120, 60) means: left=10, top=30, width=120, height=60 — so its right edge is at X=130 and bottom edge at Y=90.

26.2 Lines and Rectangles

LinesRects.vb — Visual Basic 2026
Private Sub picBox_Paint(...) Handles picBox.Paint
    Dim g = e.Graphics
    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

    ' --- Lines ---
    Using pen As New Pen(Color.Black, 1)
        g.DrawLine(pen, 10, 10, 200, 10)      ' horizontal
        g.DrawLine(pen, 10, 10, 10, 100)       ' vertical
        g.DrawLine(pen, 10, 10, 200, 100)      ' diagonal
    End Using

    ' Dashed line using DashStyle
    Using dashPen As New Pen(Color.Gray, 1)
        dashPen.DashStyle = Drawing2D.DashStyle.Dash
        g.DrawLine(dashPen, 10, 120, 200, 120)
    End Using

    ' --- Rectangles ---
    Using pen As New Pen(Color.Navy, 2)
        g.DrawRectangle(pen, 20, 20, 100, 60)   ' outline only
    End Using

    Using brush As New SolidBrush(Color.LightBlue)
        g.FillRectangle(brush, 140, 20, 100, 60) ' filled
    End Using

    ' Fill + outline
    Using brush As New SolidBrush(Color.Coral)
        g.FillRectangle(brush, 20, 100, 80, 40)
    End Using
    Using pen As New Pen(Color.DarkRed, 2)
        g.DrawRectangle(pen, 20, 100, 80, 40)   ' draw outline on top
    End Using

    ' Rounded rectangle (using GraphicsPath)
    Using path As New Drawing2D.GraphicsPath()
        Dim r = 12   ' corner radius
        path.AddArc(120, 100, r, r, 180, 90)
        path.AddArc(120 + 80 - r, 100, r, r, 270, 90)
        path.AddArc(120 + 80 - r, 100 + 40 - r, r, r, 0, 90)
        path.AddArc(120, 100 + 40 - r, r, r, 90, 90)
        path.CloseFigure()
        Using brush As New SolidBrush(Color.MediumPurple)
            g.FillPath(brush, path)
        End Using
    End Using
End Sub
Try It — Simulation 26.1: Lines & Rectangles Playground

Configure a shape and click Draw. The canvas shows the result and the code panel shows the exact VB DrawLine / DrawRectangle / FillRectangle call that produced it.

Lines & Rectangles Playground
Shape:
Color:
Width (pen):

26.3 Ellipses, Circles, and Arcs

Ellipses and circles are drawn using a bounding rectangle — the ellipse fits exactly inside that rectangle. A circle is simply an ellipse whose bounding rectangle is a square. DrawArc draws a portion of the ellipse between a start angle and sweep angle (both in degrees, measured clockwise from 3 o'clock).

Ellipses.vb — Visual Basic 2026
' Ellipse: fits inside bounding rect (x, y, width, height)
g.DrawEllipse(New Pen(Color.Blue, 2), 10, 10, 150, 80)    ' outline
g.FillEllipse(New SolidBrush(Color.SkyBlue), 10, 10, 150, 80) ' filled

' Circle: width = height
g.FillEllipse(New SolidBrush(Color.Gold), 50, 50, 80, 80)   ' filled circle r=40

' Arc: part of an ellipse
' startAngle: 0=right, 90=bottom, 180=left, 270=top (clockwise)
' sweepAngle: degrees to sweep clockwise from startAngle
Using pen As New Pen(Color.Red, 3)
    g.DrawArc(pen, 10, 110, 100, 100, 0, 270)  ' ¾ of a circle
End Using

' Concentric circles (target / radar effect)
For r = 10 To 80 Step 20
    Dim cx = 120 : Dim cy = 100
    Using pen As New Pen(Color.FromArgb(255 - r * 2, 0, 120, 200), 2)
        g.DrawEllipse(pen, cx - r, cy - r, r * 2, r * 2)
    End Using
Next

' Progress ring (arc showing percentage)
Dim pct = 75
Dim sweep = 360 * pct \ 100
g.DrawArc(New Pen(Color.LimeGreen, 8), 20, 20, 80, 80, -90, sweep)  ' -90 starts at top
Try It — Simulation 26.2: Ellipses & Arcs

Draw circles, ellipses, arcs, and concentric rings. Adjust the start angle and sweep to understand the arc coordinate system, then build a progress ring.

Ellipses & Arcs Playground
Shape:
Color:
Arc start°:
Sweep°:

26.4 Drawing Text with DrawString

DrawString renders text on any drawing surface. You need a Font object (name, size, style) and a Brush for color. Use MeasureString to calculate text dimensions for centering or wrapping.

DrawText.vb — Visual Basic 2026
' --- Basic text ---
Using font  As New Font("Segoe UI", 14, FontStyle.Regular)
Using brush As New SolidBrush(Color.Black)
    g.DrawString("Hello, VB 2026!", font, brush, 10, 10)
End Using : End Using

' --- Bold, Italic, Underline ---
Using boldFont  As New Font("Arial", 12, FontStyle.Bold)
Using italFont  As New Font("Arial", 12, FontStyle.Italic)
Using underFont As New Font("Arial", 12, FontStyle.Underline)
Using brush     As New SolidBrush(Color.DarkBlue)
    g.DrawString("Bold",       boldFont,  brush, 10, 50)
    g.DrawString("Italic",     italFont,  brush, 10, 75)
    g.DrawString("Underline", underFont, brush, 10, 100)
End Using : End Using : End Using : End Using

' --- Centred text using MeasureString ---
Dim text = "Centred Title"
Using font  As New Font("Segoe UI", 16, FontStyle.Bold)
Using brush As New SolidBrush(Color.Navy)
    Dim sz = g.MeasureString(text, font)
    Dim x  = (picBox.Width  - sz.Width)  / 2
    Dim y  = (picBox.Height - sz.Height) / 2
    g.DrawString(text, font, brush, x, y)
End Using : End Using

' --- Text inside a rectangle with StringFormat ---
Dim rect As New Rectangle(10, 10, 200, 60)
Dim fmt  As New StringFormat()
fmt.Alignment     = StringAlignment.Center    ' horizontal
fmt.LineAlignment = StringAlignment.Center    ' vertical
Using font  As New Font("Segoe UI", 12)
Using brush As New SolidBrush(Color.White)
    g.FillRectangle(New SolidBrush(Color.SteelBlue), rect)
    g.DrawString("Vertically & Horizontally Centred", font, brush, rect, fmt)
End Using : End Using
Try It — Simulation 26.3: DrawString Text Renderer

Type text, choose font settings, and see how DrawString renders it — including automatic centring via MeasureString.

DrawString — Text Renderer
Text:
Font:
Size:
Style:
Color:
Align:

26.5 Polygons and Pie Charts

Polygons take an array of Point structures. VB automatically closes the shape by connecting the last point back to the first. Pie slices use DrawPie/FillPie with the same bounding rectangle as an ellipse, plus start and sweep angles.

PolygonPie.vb — Visual Basic 2026
' --- Triangle ---
Dim tri() = {
    New Point(100, 10),
    New Point(180, 130),
    New Point(20,  130)
}
g.FillPolygon(New SolidBrush(Color.LightGreen), tri)
g.DrawPolygon(New Pen(Color.DarkGreen, 2), tri)

' --- Regular hexagon (calculated with trig) ---
Dim cx = 150, cy = 100, radius = 60
Dim hex(5) As Point
For i = 0 To 5
    Dim angle = Math.PI * (2 * i - 1) / 6    ' 60° steps, flat-top orientation
    hex(i) = New Point(cx + CInt(radius * Math.Cos(angle)),
                        cy + CInt(radius * Math.Sin(angle)))
Next
g.FillPolygon(New SolidBrush(Color.SteelBlue), hex)

' --- Pie chart slices ---
' bounding rect: x=10, y=10, width=200, height=200
' Angles: 0° = 3-o'clock, clockwise. Use -90 to start at 12.
g.FillPie(New SolidBrush(Color.Red),    10, 10, 200, 200, -90, 108) ' 30%
g.FillPie(New SolidBrush(Color.Blue),   10, 10, 200, 200,  18, 144) ' 40%
g.FillPie(New SolidBrush(Color.Green),  10, 10, 200, 200, 162,  72) ' 20%
g.FillPie(New SolidBrush(Color.Orange), 10, 10, 200, 200, 234,  36) ' 10%

' Exploded slice (offset one slice from the centre)
Dim explodeDist = 12
Dim midAngle    = Math.PI * (-90 + 108 / 2) / 180   ' midpoint of first slice
Dim offX = CInt(explodeDist * Math.Cos(midAngle))
Dim offY = CInt(explodeDist * Math.Sin(midAngle))
g.FillPie(New SolidBrush(Color.Red), 10 + offX, 10 + offY, 200, 200, -90, 108)
Try It — Simulation 26.4: Pie Chart Builder

Enter up to 5 data values with labels. The chart auto-calculates sweep angles, draws each FillPie slice, and shows the exact VB code — including the running start angle.

Pie Chart Builder — FillPie Demo

26.6 Gradient Fills and Color

The LinearGradientBrush smoothly transitions between two colours along a line. PathGradientBrush radiates a gradient from a centre point. Use Color.FromArgb(alpha, r, g, b) to set transparency (alpha 0 = fully transparent, 255 = fully opaque).

Gradients.vb — Visual Basic 2026
Imports System.Drawing.Drawing2D

' --- Horizontal gradient ---
Using lgb As New LinearGradientBrush(
        New Point(0, 0), New Point(200, 0),
        Color.DodgerBlue, Color.MediumPurple)
    g.FillRectangle(lgb, 10, 10, 200, 50)
End Using

' --- Vertical gradient ---
Using lgb As New LinearGradientBrush(
        New Point(0, 0), New Point(0, 80),
        Color.Orange, Color.OrangeRed)
    g.FillRectangle(lgb, 10, 80, 200, 80)
End Using

' --- Diagonal gradient ---
Using lgb As New LinearGradientBrush(
        New Point(230, 0), New Point(430, 170),
        Color.LimeGreen, Color.Navy)
    g.FillEllipse(lgb, 230, 10, 180, 160)
End Using

' --- Transparent overlay ---
Using brush As New SolidBrush(Color.FromArgb(120, Color.Red))
    g.FillEllipse(brush, 60, 20, 100, 100)   ' 47% opaque
End Using

' --- PathGradientBrush: radial from centre ---
Dim pts() = {New Point(150,10), New Point(250,80),
              New Point(200,160), New Point(100,160),
              New Point(50,80)}
Using pgb As New PathGradientBrush(pts)
    pgb.CenterColor     = Color.White
    pgb.SurroundColors  = {Color.DodgerBlue}
    g.FillPolygon(pgb, pts)
End Using
Try It — Simulation 26.5: Full Drawing Scene

A complete drawing scene combining gradients, polygons, ellipses, text, and transparency — all in a single Paint event. Use the preset buttons to switch scenes, then inspect the full VB code.

Full Drawing Scene — Paint Event Demo

26.7 GitHub Copilot — Animated Clock

GitHub Copilot — Timer-Driven Animated Clock
You typed: ' Draw an analog clock using GDI+ — Timer fires every 1 s, rotate hour/minute/second hands with trigonometry, draw hour marks, shade the face with a radial gradient.'
' Analog clock — runs on Timer1.Interval = 1000.
Private Sub picClock_Paint(...) Handles picClock.Paint
    Dim g = e.Graphics
    g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

    Dim cx = picClock.Width  \ 2
    Dim cy = picClock.Height \ 2
    Dim r  = Math.Min(cx, cy) - 10

    ' Radial gradient face
    Dim pts() = {New Point(cx, cy)}
    Using pgb As New Drawing2D.PathGradientBrush(pts)
        pgb.CenterPoint    = New PointF(cx, cy)
        pgb.CenterColor    = Color.White
        pgb.SurroundColors = {Color.LightSteelBlue}
        pgb.FocusScales    = New PointF(0, 0)
        g.FillEllipse(pgb, cx - r, cy - r, r * 2, r * 2)
    End Using
    g.DrawEllipse(New Pen(Color.Navy, 3), cx - r, cy - r, r * 2, r * 2)

    ' Hour marks
    For i = 0 To 11
        Dim a  = Math.PI * (2 * i) / 12 - Math.PI / 2
        Dim x1 = cx + CInt((r - 8)  * Math.Cos(a))
        Dim y1 = cy + CInt((r - 8)  * Math.Sin(a))
        Dim x2 = cx + CInt((r - 20) * Math.Cos(a))
        Dim y2 = cy + CInt((r - 20) * Math.Sin(a))
        g.DrawLine(New Pen(Color.Navy, 2), x1, y1, x2, y2)
    Next

    ' Hands
    Dim now = DateTime.Now
    DrawHand(g, cx, cy, r * 0.5,
        Math.PI * (2 * now.Hour + now.Minute / 60) / 12 - Math.PI / 2,
        Color.Navy, 5)
    DrawHand(g, cx, cy, r * 0.75,
        Math.PI * (2 * now.Minute + now.Second / 60) / 60 - Math.PI / 2,
        Color.DarkBlue, 3)
    DrawHand(g, cx, cy, r * 0.85,
        Math.PI * 2 * now.Second / 60 - Math.PI / 2,
        Color.Red, 1)
End Sub

Private Sub DrawHand(g As Graphics, cx%, cy%, length#, angle#, c As Color, thick%)
    Dim x = cx + CInt(length * Math.Cos(angle))
    Dim y = cy + CInt(length * Math.Sin(angle))
    g.DrawLine(New Pen(c, thick), cx, cy, x, y)
End Sub

Private Sub Timer1_Tick(...) Handles Timer1.Tick
    picClock.Invalidate()   ' redraw every second
End Sub
Copilot Chat Prompts for This Lesson

Try these in the Copilot Chat panel:

  • "Draw a bar chart from a Dictionary(Of String, Integer) where keys are month names and values are sales figures — auto-scale bars to fit the PictureBox height"
  • "Create a Spirograph — use two nested For loops with Math.Sin/Cos to draw a parametric curve with configurable R, r, and d constants"
  • "Draw a star polygon with n points using FillPolygon — calculate the outer and inner radius points alternating to create the star shape"
  • "Add a rubber-band selection rectangle: track MouseDown, MouseMove, MouseUp coordinates and draw a dashed rectangle updated in real time"

Lesson Summary

  • All GDI+ drawing happens inside the Paint event. Get the drawing surface from e.Graphics. Call control.Invalidate() to request a repaint — never store the Graphics object between events.
  • Origin (0, 0) is top-left. X increases right; Y increases downward. Shapes use (x, y, width, height) bounding rectangle coordinates.
  • Always wrap Pen, Brush, and Font in Using blocks — they hold GDI+ handles that must be released immediately after drawing.
  • DrawLine / DrawRectangle / DrawEllipse / DrawPolygon draw outlines (need a Pen). Fill variants fill the interior (need a Brush). You can layer both.
  • Set g.SmoothingMode = AntiAlias for smooth curves. Arcs measure angles in degrees, clockwise from 3 o'clock (use −90° to start at 12 o'clock).
  • DrawString renders text with a Font + Brush. Use MeasureString to compute text dimensions for precise centring. StringFormat controls horizontal and vertical alignment inside a rectangle.
  • LinearGradientBrush fills shapes with smooth colour transitions. Color.FromArgb(alpha, R, G, B) controls transparency (0–255).
  • Combine GDI+ with Timer: set Timer.Interval, call Invalidate() in the Tick handler, and use DateTime.Now + trigonometry for animated clocks, progress bars, and simulations.

Exercises

Exercise 26.1 — Bar Chart Generator

  • Accept 5 data values in TextBoxes. Compute the maximum and scale each bar to fill the PictureBox height proportionally.
  • Draw each bar as a gradient-filled rectangle (LinearGradientBrush) with a contrasting outline.
  • Label the value above each bar and the category name below using DrawString + MeasureString to centre both.
  • Add a horizontal grid line at 25%, 50%, 75%, 100% using a dashed Pen.
  • Copilot challenge: "Auto-resize the chart when the PictureBox is resized — calculate bar width and height dynamically from picBox.Width and picBox.Height"

Exercise 26.2 — Analog Clock

  • Build a PictureBox-based analog clock using the Copilot example as a starting point.
  • Add minute marks (60 shorter lines between the 12 hour marks).
  • Show the current time as a digital readout below the clock face using DrawString.
  • Add a start/stop button that enables/disables Timer1.
  • Copilot challenge: "Draw a dropshadow under the clock face using a semi-transparent SolidBrush offset by 4px right and 4px down"

Exercise 26.3 — Pie Chart with Legend

  • Define 5 named data values (budget categories). Calculate each slice's sweep angle as value / total * 360.
  • Draw each slice with FillPie using a preset color palette, then outline with DrawPie.
  • Explode the largest slice by offsetting it along the radius midpoint.
  • Draw a legend: coloured square + label + percentage, stacked vertically to the right of the pie.
  • Copilot challenge: "Add mouse-click detection: on MouseDown, compute which slice was clicked using the angle from the centre point, and highlight that slice"

Next: Lesson 27 — Using the Timer

Deep dive into the Timer control — Tick events, intervals, start/stop, countdown timers, stopwatches, and combining Timer with GDI+ for smooth animation.

Continue »

Related Resources


Featured Books

Visual Basic 2022 Made Easy

Visual Basic 2022 Made Easy

by Dr. Liew Voon Kiong

GDI+ graphics chapters with complete chart and animation examples.

View on Amazon →
VB Programming With Code Examples

VB Programming With Code Examples

by Dr. Liew Voon Kiong

Worked programs including drawing applications, clocks, and animated graphics.

View on Amazon →