freehand drawing application

justlearning

Member
Joined
Dec 11, 2008
Messages
16
Programming Experience
Beginner
Write a program that allows the user to draw 'free-hand' images with the mouse in a PictureBox. Be sure to provide the following:

A Button to allow users to clear the image in the PictureBox
A ComboBox to allow users to change the color of the pen
A set of radio buttons to set the drawing width
A menu containing at least the following items:
Clear
Change Color (then provide the colors that are in your ComboBox)
Change width (then provide the sizes in your RadioButtons)
Be sure that when the user makes a selection from the menu, the appropriate control (Button, ComboBox or RadioButton) is updated to reflect the user's choice




I have gotten to the point where the user is able to draw in my picture box but I cannot figure out how to change the color or size of the brush. Right now, you can see below, I have both the color and the size set to a specific color and size. Unfortunately I do not know how to take this out and put in a string that reads the combobox colors and the radiobuttons selection. I would like to set the default color to black and the default size to 10, 10. If you can help please let me know. Thanks so much.

VB.NET:
Public Class Form1
    'Set shouldpaint to true/false to use for mousedown/mouseup
    Dim shouldpaint As Boolean = False

    'Form load section
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ColorBox.SelectedItem(0) = Color.Aqua
        ColorBox.SelectedItem(1) = Color.Blue
        ColorBox.SelectedItem(2) = Color.Red
    End Sub
    Private Sub Drawpb_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Drawpb.MouseDown
        'Set drawpd to draw when mouse was held down
        shouldpaint = True
    End Sub

    Private Sub Drawpb_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Drawpb.MouseUp
        'Set drawpd not to draw when mouse was up
        shouldpaint = False
    End Sub
    Private Sub Drawpb_mousemove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Drawpb.MouseMove
        If shouldpaint Then
            'Declare g for graphics
            Dim g As System.Drawing.Graphics
            'set drawpad as site for freehand drawing
            g = Drawpb.CreateGraphics()
            'Set brush color as black and size of brush to 20, 20
            g.FillEllipse( _
New SolidBrush(Color.Black), e.X, e.Y, 20, 20)
        End If
    End Sub
    'Exit Button
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'End program
        Me.Close()
        End
    End Sub
    'Clear Button 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'Clear Drawpad
        Drawpb.Refresh()
    End Sub
    'Menu strip: Close
    Private Sub CloseToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseToolStripMenuItem.Click
        'End Program
        Me.Close()
        End
    End Sub
    'Menu Strip: Clear
    Private Sub ClearToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ClearToolStripMenuItem.Click
        'Clear Drawpad
        Drawpb.Refresh()
    End Sub
    'Color ComboBox
    Private Sub ColorBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ColorBox.SelectedIndexChanged
    
    End Sub
End Class

I also included a screen shot of my gui.

Please let me know if you can help me. Thanks again.
 

Attachments

  • screenshot.jpg
    screenshot.jpg
    209.5 KB · Views: 108
1. I cropped your image and reattached it. Please be careful in future not to attach images that are 4 times the size they need to be.

2. There's a major issue with your code as it is now. You should not be doing the drawing in the MouseMove event handler. Try doing some drawing and then minimise and restore your form. Poof! All your drawing is gone.

When using GDI+ to draw on controls you must do your drawing on the Paint event of that control. In the MouseMove event you need to calculate the data required to do the drawing and then assign that data to member variables. You then force a repaint to raise the Paint event. In the OnPaint method or the Paint event handler you get that data from those member variables and then use the Graphics object provided to perform the drawing. You do NOT create your own Graphics object.

To force a repaint you can either call Refresh or Invalidate and Update. Refresh will cause the entire control to be repainted, which is necessary sometimes but generally undesirable. That's because painting to the screen is slow so if you repeatedly repaint the entire control it can lead to flickering. It's better to call Invalidate and specify only the area that has changed, then call Update. That will repaint only what's required. You may like to take a look at this as a simple demonstration of these principles.

3. As I said in 2, you need to store the data required to perform the drawing in member variables. Each dot you draw is going to need its location, size and colour stored so that every time you need to redraw that dot the complete information is available. You would store the current colour and current size in member variables and, each time you need to add a new dot you can get those values and store them with the location.

You'll see in that drawing demo of mine I define a Line class. I would suggest that you define a class that represents a dot. It would have three properties: Location, Size and Colour. On the Paint event you will then simply loop through a List of instances of that type and draw each one, just as I do for the Lines in my demo.
 
Here's the beginnings of what that would look like:
VB.NET:
Public Class Dot

    Private _location As Point
    Private _diameter As Integer
    Private _colour As Color


    Public ReadOnly Property Location() As Point
        Get
            Return Me._location
        End Get
    End Property

    Public ReadOnly Property Diameter() As Integer
        Get
            Return Me._diameter
        End Get
    End Property

    Public ReadOnly Property Colour() As Color
        Get
            Return Me._colour
        End Get
    End Property


    Public Sub New(ByVal location As Point, ByVal diameter As Integer, ByVal colour As Color)
        Me._location = location
        Me._diameter = diameter
        Me._colour = colour
    End Sub

End Class
VB.NET:
Public Class Form1

    Private dots As New List(Of Dot)

    Private currentColour As Color
    Private currentDiameter As Integer

    Private isDrawing As Boolean = False


    Private Sub PictureBox1_MouseMove(ByVal sender As Object, _
                                      ByVal e As MouseEventArgs) Handles PictureBox1.MouseMove
        If Me.isDrawing Then
            'Create a new Dot and add it to the List using the current
            'mouse coordinates, current diameter and current colour.

            'Force a repaint.
            Me.PictureBox1.Invalidate() 'You should specify the area that contains the new dot here.
            Me.PictureBox1.Update()
        End If
    End Sub

    Private Sub PictureBox1_Paint(ByVal sender As Object, _
                                  ByVal e As PaintEventArgs) Handles PictureBox1.Paint
        For Each d As Dot In Me.dots
            'Draw d using e.Graphics.
        Next
    End Sub

End Class
 
I often use following method to draw things using gdi+ :
1. make a blank bitmap: dim bmp as new bitmap(width, height). Width and height is the size of the control area you want to draw in.
2. make a graphics object out of the bitmap: dim g as graphics=graphics.frombitmap(bmp)
3. draw things
4. put the bitmap on the background of your control: control.backgroundimage=bmp

This way you can avoid putting code to the Paint event procedure. You can use your own procedures. Don´t forget to call the procedure after resizing control. You can also easily save and load pictures from files.
 
I often use following method to draw things using gdi+ :
1. make a blank bitmap: dim bmp as new bitmap(width, height). Width and height is the size of the control area you want to draw in.
2. make a graphics object out of the bitmap: dim g as graphics=graphics.frombitmap(bmp)
3. draw things
4. put the bitmap on the background of your control: control.backgroundimage=bmp

This way you can avoid putting code to the Paint event procedure. You can use your own procedures. Don´t forget to call the procedure after resizing control. You can also easily save and load pictures from files.
The "problem" with that is that drawing on an image is permanent, while it's not on a control. This will not be an issue in some cases but in others it will. Anyway, as long as you know that it's what you need to do, drawing on the Paint event is not anything that needs to be avoided.
 
Back
Top