Public Class PaintCanvas
    Inherits System.Windows.Forms.UserControl
    ' enums...
    Public Enum GraphicTools As Integer
        CirclePen = 0
        HollowCirclePen = 1
    End Enum

    Public Enum GraphicSizes As Integer
        Small = 4
        Medium = 10
        Large = 20
    End Enum
    ' members...
    Public GraphicsItems As New ArrayList()
    Public GraphicTool As GraphicTools = GraphicTools.CirclePen
    Public GraphicSize As GraphicSizes = GraphicSizes.Medium
    Public GraphicLeftColor As Color = Color.Black
    Public GraphicRightColor As Color = Color.White
    ' DoMousePaint - respond to a mouse movement...
    Private Sub DoMousePaint(ByVal e As MouseEventArgs)

        ' store the new item somewhere...
        Dim newItem As GraphicsItem
        ' what color do we want to use?

        Dim useColor As Color = GraphicLeftColor
        If e.Button = MouseButtons.Right Then useColor = GraphicRightColor
        ' what tool are we using?
        Select Case GraphicTool

            ' circlepen?
        Case GraphicTools.CirclePen, GraphicTools.HollowCirclePen

                ' are we filled?
                Dim filled As Boolean = True
                If GraphicTool = GraphicTools.HollowCirclePen Then _
                   filled = False

                ' create a new graphics circle...
                Dim circle As New GraphicsCircle()
                circle.SetPoint(e.X, e.Y, GraphicSize, useColor, filled)
                ' store this for addition...
                newItem = circle

        End Select

        ' were we given an item?
        If Not newItem Is Nothing Then

            ' add it to the list...
            GraphicsItems.Add(newItem)

            ' invalidate...
            Invalidate(newItem.Rectangle)

        End If

    End Sub

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        '
        'PaintCanvas
        '
        Me.BackColor = System.Drawing.Color.WhiteSmoke
        Me.Name = "PaintCanvas"

    End Sub

#End Region

    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        ' is the button down?
        If e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right Then
            DoMousePaint(e)
        End If

    End Sub

    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        ' is the button down?
        If e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right Then
            DoMousePaint(e)
        End If

    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        ' go through the list...
        Dim item As GraphicsItem
        For Each item In GraphicsItems
            ' do we need to be drawn?
            If e.ClipRectangle.IntersectsWith(item.Rectangle) = True Then


                ' ask each item to draw itself...
                item.Draw(e.Graphics)
            End If
        Next

    End Sub

    Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
        ' paint the invalid region with the background brush...
        Dim backgroundBrush As New SolidBrush(BackColor)
        pevent.Graphics.FillRectangle(backgroundBrush, pevent.ClipRectangle)

        ' paint the image...
        If Not BackgroundImage Is Nothing Then

            ' find our client rectangle...
            Dim clientRectangle As New Rectangle(0, 0, Width, Height)

            ' how big is the image?
            Dim imageWidth As Integer = BackgroundImage.Width
            Dim imageHeight As Integer = BackgroundImage.Height

            ' what's the aspect ratio?
            Dim ratio As Double = _
               CType(imageHeight, Double) / CType(imageWidth, Double)

            ' scale the image...
            If imageWidth > clientRectangle.Width Then
                imageWidth = clientRectangle.Width
                imageHeight = CType(CType(imageWidth, Double) * ratio, Integer)
            Else
                imageHeight = clientRectangle.Height
                imageWidth = CType(CType(imageHeight, Double) / ratio, Integer)
            End If

            ' we just need to center the image... easy!
            Dim imageLocation As New Point( _
             (clientRectangle.Width / 2) - (imageWidth / 2), _
             (clientRectangle.Height / 2) - (imageHeight / 2))
            Dim imageSize As New Size(imageWidth, imageHeight)
            Dim imageRectangle As New Rectangle(imageLocation, imageSize)

            ' draw the image...
            pevent.Graphics.DrawImage(BackgroundImage, imageRectangle)

        End If
    End Sub

    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        Invalidate()
    End Sub
End Class
