-1

I am trying to make the program execute multiple times (instead of just once when the form loads); I have tried to do this through either the user clicking a button, or a timer that would execute the program again after it has "ticked".

I have commented out the code with errors:

Public Class Forml

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Randomize()
        Dim i As Integer
        Dim z As Integer
        z = Rnd() * 25
        For i = 0 To 2
            Dim intx As Integer = Rnd() * 420
            Dim inty As Integer = Rnd() * 420
            Dim tempBrush As Brush = New SolidBrush(Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255))
            e.Graphics.FillEllipse(tempBrush, intx, inty, 2, 2)
        Next
    End Sub

    'Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    '   Call Form1_Paint()
    'End Sub

    'Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
    '   Call Form1_Paint()
    'End Sub

End Class
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
AntonyBoys
  • 15
  • 3
  • `I have included a picture of my code` please dont do that - we need the actual code *here, in* the question. See: [Ask]. Make it easy for us to help you by not sending us elsewhere – Ňɏssa Pøngjǣrdenlarp Feb 06 '16 at 18:03
  • `call` is VB6 (and VBA imho) syntax. You call a sub/function just by writing its name with brackets: `Foo()`. I recommend encapsulating your logic from the paint handler into an own sub and call it whenever you need it. – Alex B. Feb 06 '16 at 18:19
  • I tried to improve your question by using OCR on the image of your code (please do not use an image of text information, be it code or an error message) and adding back some of your text which was unfortunately lost in an earlier edit. Please edit your question if I have anything wrong. – Andrew Morton Feb 06 '16 at 19:49

1 Answers1

0

What is seemingly a simple endeavour in this case actually turns out to be easier with a few bits of background knowledge.

  • The Form1.Paint event is raised whenever the form is deemed to need a re-paint, for example if it has been covered by another form. For this exercise, you may not be concerned with more dots appearing than your code at first appears to produce. I shall not address that issue here.

  • The e.Graphics object is not what you want if you want to persist the graphics, instead you want to use the object obtained from Control.CreateGraphics.

  • It is recommended to use the .NET framework Random class instead of VB's Rnd().

  • Some classes use resources which need to be specifically disposed of, and so they have a .Dispose() method. Graphics objects tend to be like that (also database and file operations). You can use a Using block to take care of calling Dispose for you.

And a very important point:

  • Use Option Strict On. It will help you write code that works by pointing out any errors it can detect. Set it as the default for new projects.

A couple more things I should mention are that you should take some care when naming variables, and that it makes debugging easier to separate some things out into their own variables rather than writing one long line of code.

For things like timers, where you could drag a timer onto the drawing surface, I find it better to create it in code. That way you do not have to swap back and forth between the designer and code windows to change parameters, and you don't wonder where something like "Timer1" came from.

After all that, I came up with the (not necessarily very good) code:

Option Infer On
Option Strict On

Public Class Form1

    Dim rand As New Random
    Dim tim As Timer

    Sub DrawDots(sender As Object)
        ' This sub could have been called with anything as sender, so check that
        ' it is actually a Control
        Dim self As Control = TryCast(sender, Control)
        If self Is Nothing Then
            Exit Sub
        End If

        Using g = self.CreateGraphics()

            Dim nDots = rand.Next(1, 26)
            Dim circleRadius = 20

            For i = 1 To nDots
                Dim xLoc = rand.Next(0, 420)
                Dim yLoc = rand.Next(0, 420)
                Dim col = Color.FromArgb(rand.Next(0, 256), rand.Next(0, 256), rand.Next(0, 256))

                Using br As New SolidBrush(col)
                    g.FillEllipse(br, xLoc, yLoc, circleRadius, circleRadius)
                End Using

            Next
        End Using

    End Sub

    Sub DrawDotsOnTimerTick(sender As Object, e As EventArgs)
        DrawDots(Me)

    End Sub

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
        DrawDots(sender)

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DrawDots(Me)

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        tim = New Timer
        tim.Interval = 2000
        AddHandler tim.Tick, AddressOf DrawDotsOnTimerTick
        tim.Start()

    End Sub

End Class
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • you can pass `e.Graphics` from the paint event to DrawDots() rather than using `CreateGraphics`. Elsewhere rather than calling DrawDots, just invalidate the form (at which point, DrawDots is not needed because it is the Paintevent code). . Using the paint event is what makes the drawing persist. – Ňɏssa Pøngjǣrdenlarp Feb 06 '16 at 20:45