We help IT Professionals succeed at work.

Gridlines beneath an eraseable drawing picturebox

km176351
km176351 asked
on
Medium Priority
816 Views
Last Modified: 2012-06-22
Hi,
I am trying to create a simple drawing application that allows a user to draw onto a picture box, use an eraser tool if necessary and then save the image to a file.
This is straightforward enough however I have been asked to show gridlines beneath the image. These show ok however when a user uses my eraser, they also cause the gridlines to be erased as well.
All my eraser routine is doing is drawing a white line over the picture box thus erasing any black pixels but also causing these new white pixels to be shown over the grid bitmap behind.

I think ... that I need a way of setting the pixels drawn with the eraser back to transparent if this is possible or would appreciate any other ideas people have. I've attacehed the basic code below:
Dim _guideLines As Boolean
    Dim BMP As Bitmap
    Dim BMPGL As Bitmap
    Dim GR As Graphics
    Dim GRGL As Graphics
    Dim DISP As Bitmap
    Dim DispGR As Graphics
 
    Private m_drawing As Boolean
    Private m_X As Integer
    Private m_Y As Integer
 
 
    Private cc As Pen = Pens.Black
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        BMP = New Bitmap(piccanvas.Width, piccanvas.Height)
        BMPGL = New Bitmap(piccanvas.Width, piccanvas.Height)
        DISP = New Bitmap(piccanvas.Width, piccanvas.Height)
        GR = Graphics.FromImage(BMP)
        GRGL = Graphics.FromImage(BMPGL)
 
        DispGR = Graphics.FromImage(DISP)
        DispGR.Clear(Color.White)
 
        DrawGridLines()
 
    End Sub
 
    Private Sub DrawGridLines()
        Dim x As Integer
        Dim y As Integer
 
        For x = 1 To 10
            For y = 1 To 10
                GRGL.DrawLine(Pens.Blue, (x * 50), 0, (x * 50), piccanvas.Height)
                GRGL.DrawLine(Pens.Blue, 0, y * 50, piccanvas.Width, y * 50)
            Next
        Next
    End Sub
 
    Private Sub CheckBox2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox2.Click
        If CheckBox2.checked Then
            cc = Pens.White
        Else
            cc = Pens.Black
        End If
    End Sub
 
 
    Private Sub CheckBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.Click
        If _guideLines Then
            _guideLines = False
            CheckBox1.Checked = False
 
            DispGR.Clear(Color.White)
            DispGR.DrawImage(BMP, New Point(0, 0))
            piccanvas.Image = DISP
 
        Else
            _guideLines = True
            CheckBox1.Checked = True
 
            DispGR.Clear(Color.White)
            DispGR.DrawImage(BMPGL, New Point(0, 0))
            DispGR.DrawImage(BMP, New Point(0, 0))
            piccanvas.Image = DISP
        End If
    End Sub
 
    Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseDown
        m_drawing = True
        m_X = e.X
        m_Y = e.Y
    End Sub
 
    Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseMove
        If Not m_drawing Then Exit Sub
        GR.DrawLine(cc, m_X, m_Y, e.X, e.Y)
        m_X = e.X
        m_Y = e.Y
 
        DispGR.DrawImage(BMP, New Point(0, 0))
        piccanvas.Image = DISP
    End Sub
 
    Private Sub PictureBox1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseUp
        m_drawing = False
    End Sub

Open in new window

Comment
Watch Question

Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Comment out your DrawGridLines() call:

        ' DrawGridLines()

...and try drawing the Gridlines in the Paint() Event intead:
    Private Sub piccanvas_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles piccanvas.Paint
        For x As Integer = 1 To 10
            For y As Integer = 1 To 10
                e.Graphics.DrawLine(Pens.Blue, (x * 50), 0, (x * 50), piccanvas.Height)
                e.Graphics.DrawLine(Pens.Blue, 0, y * 50, piccanvas.Width, y * 50)
            Next
        Next
    End Sub

Open in new window

Author

Commented:
Close... very close

But ideally the grid needs to be behind the image so that if you drew a line directly over a grid line, you would see the drawn line rather than the grid line

Author

Commented:
Also,
Because the image will be saved to file, I will need the saved image to look correct too:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        DISP.Save("c:\Test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
    End Sub
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
You want the gridlines to be part of the finished image?

Author

Commented:
Hi sorry for not being clearer but ideally yes.
The effect I am trying to achieve is that the user is confronted with a canvas with grid lines displayed on it. When the user draws on the canvas, the drawn features appear on top of the grid lines. When the user uses the eraser, only the drawn features get erased and not the gridlines.
This picture as a whole (including the gridlines) should then be saveable to file.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009

Commented:
Ok...no problem.  I'm pretty sure I have a simple workable solution for you.  What version VB.Net are you running though?

Author

Commented:
Hi,
I'm using 2005 although I can quite easily switch to 2008 if necessary
High School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
CERTIFIED EXPERT
Top Expert 2009
Commented:
Try this out with a New Project.  It has a PictureBox (piccanvas), two RadioButtons, and a Button.
Imports System.Drawing.Drawing2D
Public Class Form1
 
    Private Class Squiggle
        Public Shared Width As Integer = 8
        Public GP As New GraphicsPath
        Public Drawn As Boolean = True
    End Class
 
    Private lastX, lastY As Integer
    Private S As Squiggle
    Private Squiggles As New List(Of Squiggle)
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim bmp As New Bitmap(piccanvas.ClientRectangle.Width, piccanvas.ClientRectangle.Height)
        Dim G As Graphics = Graphics.FromImage(bmp)
        For x As Integer = 50 To bmp.Width Step 50
            For y As Integer = 50 To bmp.Height Step 50
                G.DrawLine(Pens.Blue, x, 0, x, bmp.Height)
                G.DrawLine(Pens.Blue, 0, y, bmp.Width, y)
            Next
        Next
        G.Dispose()
        piccanvas.Image = bmp
    End Sub
 
    Private Sub piccanvas_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            lastX = e.X
            lastY = e.Y
            S = New Squiggle
            S.Drawn = RadioButton1.Checked
        End If
    End Sub
 
    Private Sub piccanvas_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then
            S.GP.AddLine(lastX, lastY, e.X, e.Y)
            lastX = e.X
            lastY = e.Y
            piccanvas.Refresh()
        End If
    End Sub
 
    Private Sub piccanvas_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles piccanvas.MouseUp
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Dim p As New Pen(Color.Black, Squiggle.Width)
            S.GP.Widen(p)
            p.Dispose()
            Squiggles.Add(S)
            S = Nothing
            piccanvas.Refresh()
        End If
    End Sub
 
    Private Sub piccanvas_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles piccanvas.Paint
        Dim R As New Region
        R.MakeEmpty()
 
        For Each S As Squiggle In Squiggles
            If S.Drawn Then
                R.Union(S.GP)
            Else
                R.Exclude(S.GP)
            End If
        Next
 
        If Not IsNothing(S) Then
            Dim tempGP As GraphicsPath = S.GP.Clone
            Dim p As New Pen(Color.Black, Squiggle.Width)
            tempGP.Widen(p)
            p.Dispose()
            If S.Drawn Then
                R.Union(tempGP)
            Else
                R.Exclude(tempGP)
            End If
        End If
 
        e.Graphics.SetClip(R, CombineMode.Replace)
        e.Graphics.FillRectangle(Brushes.Black, piccanvas.ClientRectangle)
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim bmp As New Bitmap(piccanvas.ClientRectangle.Width, piccanvas.ClientRectangle.Height)
        piccanvas.DrawToBitmap(bmp, piccanvas.ClientRectangle)
        bmp.Save(System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "drawing.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg)
    End Sub
 
End Class

Open in new window

Squiggle.jpg

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
That is exactly the functionality I was trying to achieve - Many thanks!
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.