Search code examples
vb.neteventshandlerpaintbasic

How to use the Paint event more than once on a form?


Okay, so I am trying to make a program that each time you click (doesn't matter where) a random colored, and sized circle appears where you happened to click. however, the only way I can add a shape is via Paint event. here is the code I have now:

Private Sub Form1_Paint(ByVal Sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint


    Using Brush1 As New SolidBrush(Color.Orange)
            e.Graphics.FillEllipse(Brush1, MousePosition.X, MousePosition.Y, 100, 100)
        End Using

End Sub

I need to know a line of code that I can use in a mouse click event, that will re-run this sub. I know how to change the size, and make it random, I just don't know how to run this sub multiple times, more precisely; run this sub once after each mouse click. If someone can help, I would appreciate it!


Solution

  • Just as Plutonix explained, a refresh is handled by calling the Invalidate method.

    The thing you need to remember is that whatever is painted on a surface is not persistent, so you need to redraw the whole screen every time. There are, of course, many ways in which this can be optimized for performance purposes, as this process can be extremely CPU intensive; specially, since GDI+ is not hardware accelerated.

    So, what you need to do is:

    1. Record every click (x, y position) and store it

    2. Since the radius of each circle is random, determine the radius when the user clicks the form, then store it along with the x, y position of the click

    3. Then, have the Paint event re-draw each stored sequence of clicks (with their respective radii) and re-draw each circle over and over.

    Here's an implementation that will do the trick. Just paste this code inside any Form's class to test it:

    Private Class Circle
        Public ReadOnly Property Center As Point
        Public ReadOnly Property Radius As Integer
    
        Public Sub New(center As Point, radius As Integer)
            Me.Center = center
            Me.Radius = radius
        End Sub
    End Class
    
    Private circles As New List(Of Circle)
    
    Private radiusRandomizer As New Random()
    
    Private Sub FormLoad(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) ' Not really necessary in this app...
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.ResizeRedraw, True)
        Me.SetStyle(ControlStyles.UserPaint, True)
    End Sub
    
    Private Sub FormMouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
        circles.Add(New Circle(New Point(e.X, e.Y), radiusRandomizer.Next(10, 100)))
        Me.Invalidate()
    End Sub
    
    Private Sub FormPaint(sender As Object, e As PaintEventArgs) Handles Me.Paint
        Dim g As Graphics = e.Graphics
    
        g.Clear(Color.Black)
    
        Using p As New Pen(Color.White)
            For Each c In circles
                g.DrawEllipse(p, c.Center.X - c.Radius \ 2, c.Center.Y - c.Radius \ 2, c.Radius, c.Radius)
            Next
        End Using
    End Sub
    

    Here's what you'll get after a few clicks on the form enter image description here