Private Const GRID_SPACING As Integer = 10
' True while we are drawing the new line.
Private m_Drawing As Boolean
' Buffer for erasing rubberband lines.
Private m_BufferBitmap As Bitmap
Private m_BufferGraphics As Graphics
' The mouse position.
Private m_X1 As Integer
Private m_Y1 As Integer
Private m_X2 As Integer
Private m_Y2 As Integer
Private Sub SaveSnapshot()
    Dim new_bitmap As Bitmap
    ' Make a new bitmap that fits the PictureBox.
    new_bitmap = New Bitmap(picCanvas.Size.Width, _
        picCanvas.Size.Height)
    m_BufferGraphics = Graphics.FromImage(new_bitmap)
    ' Clear the new bitmap.
    m_BufferGraphics.Clear(picCanvas.BackColor)
    ' Draw the positioning grid.
    DrawGrid(new_bitmap)
    ' Copy the existing bitmap's contents into
    ' the new bitmap.
    If Not (m_BufferBitmap Is Nothing) Then
        m_BufferGraphics.DrawImage(m_BufferBitmap, 0, 0)
    End If
    ' Save the new bitmap and graphics objects.
    m_BufferBitmap = new_bitmap
End Sub
' Redraw the saved buffer.
Private Sub DrawPicture(ByVal gr As Graphics)
    If Not (m_BufferBitmap Is Nothing) Then _
        gr.DrawImage(m_BufferBitmap, 0, 0)
End Sub
' Start drawing a rubberband line.
Private Sub picCanvas_MouseDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
    picCanvas.MouseDown
    ' Do nothing if this isn'tthe left mouse button.
    If e.Button <> MouseButtons.Left Then Exit Sub
    m_Drawing = True
    ' Save a snapshot of the form.
    SaveSnapshot()
    ' Save the current mouse position.
    m_X1 = e.X
    m_Y1 = e.Y
    SnapToGrid(m_X1, m_Y1)
    m_X2 = m_X1
    m_Y2 = m_Y1
End Sub
' Continue drawing the rubberband line.
Private Sub picCanvas_MouseMove(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
    picCanvas.MouseMove
    ' Do nothing if we're not drawing.
    If Not m_Drawing Then Exit Sub
    ' Save the new point.
    m_X2 = e.X
    m_Y2 = e.Y
    SnapToGrid(m_X2, m_Y2)
    ' Erase the previous line.
    Dim gr As Graphics = picCanvas.CreateGraphics()
    DrawPicture(gr)
    ' Draw the new line directly on the PictureBox.
    gr.DrawLine(Pens.Gray, m_X1, m_Y1, m_X2, m_Y2)
End Sub
' Finish drawing the new line.
Private Sub picCanvas_MouseUp(ByVal sender As Object, ByVal _
    e As System.Windows.Forms.MouseEventArgs) Handles _
    picCanvas.MouseUp
    ' Do nothing if we're not drawing.
    If Not m_Drawing Then Exit Sub
    m_Drawing = False
    ' Draw the new line permanently on the buffer.
    m_BufferGraphics.DrawLine( _
        Pens.Blue, m_X1, m_Y1, m_X2, m_Y2)
    ' Redraw to show the new line.
    DrawPicture(picCanvas.CreateGraphics())
End Sub
' Snap the point to the grid.
Private Sub SnapToGrid(ByRef X As Integer, ByRef Y As _
    Integer)
    X = GRID_SPACING * CInt(X / GRID_SPACING)
    Y = GRID_SPACING * CInt(Y / GRID_SPACING)
End Sub
' Draw the positioning grid.
Private Sub DrawGrid(ByVal bm As Bitmap)
    For Y As Integer = 0 To bm.Height - 1 Step GRID_SPACING
        For X As Integer = 0 To bm.Width - 1 Step _
            GRID_SPACING
            bm.SetPixel(X, Y, Color.Black)
        Next X
    Next Y
End Sub
' Redraw the picture.
Private Sub picCanvas_Paint(ByVal sender As Object, ByVal e _
    As System.Windows.Forms.PaintEventArgs) Handles _
    picCanvas.Paint
    DrawPicture(e.Graphics)
End Sub
' Make the initial grid.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As _
    System.EventArgs) Handles MyBase.Load
    SaveSnapshot()
End Sub
' Make the new grid.
Private Sub picCanvas_Resize(ByVal sender As Object, ByVal _
    e As System.EventArgs) Handles picCanvas.Resize
    SaveSnapshot()
End Sub
               |