vb.netbuttonclickform-load

Code to draw works in button click event but not in form load


why can I run the following code faultless under a button even but not under the form load even?

For Each line As String In System.IO.File.ReadAllLines("c:\pos.xml")

    If line.Contains("<POS>") = True Then

        Dim tagless As String = StripTags(line)

        Dim parts As String() = tagless.Split(New Char() {","})
        Dim XVAL As Decimal = parts(0)
        Dim YVAL As Decimal = parts(1)

        'paint markers...
        Dim myBrush As New SolidBrush(Color.FromArgb(128, Color.Red))
        Dim formGraphics As System.Drawing.Graphics
        formGraphics = Me.PictureBox1.CreateGraphics()
        formGraphics.FillEllipse(myBrush, New Rectangle(XVAL - 35, YVAL - 35, 70, 70))

        myBrush.Dispose()
        formGraphics.Dispose()

    End If
Next

Here is the striptag function if requierd...

    Function StripTags(ByVal html As String) As String
    ' Remove HTML tags.
    Return Regex.Replace(html, "<.*?>", "")
End Function

Solution

  • The right way to draw is hardly ever with CreateGraphics. This will draw something that does not persist. When the area is invalidated such as the form is minimized or another form/app is dragged over it, your shapes will disappear.

    You should also turn on Option Strict. There are numerous type errors in the code. For instance there is no Rectangle constructor which takes a Decimal. That is not even the right Class for non integers, but RectangleF doesn't take a Decimal either.


    The core problem is that the form is shown at the end of the form load event. So, your code is running/drawing before the form is visible and nothing is shown. Even if the form was already showing, whatever you draw would not be retained if the user minimized the form or moved another window across it.

    ' form level list to store the data
    Private XY As New List(Of PointF)       ' pts
    

    Then in form load event, read the data and add to the list

    For Each line As String In System.IO.File.ReadAllLines("...")
        If line.Contains("<POS>") = True Then
            Dim tagless As String = StripTags(line)
    
            '                                      c required under Option Strict
            Dim parts As String() = tagless.Split(New Char() {","c})
            ' convert values to single. create a PointF
            Dim ptF As New PointF(Convert.ToSingle(parts(0)), Convert.ToSingle(parts(1)))
            ' add to list
            XY.Add(ptF)
       End If
    Next
    

    The next thing that happens should be the form being shown and the paint event invoked. The data is used in the Paint Event:

    Dim rectF As RectangleF
    Using myB As New SolidBrush(Color.FromArgb(128, Color.Red))
        For Each ptF As PointF In XY
            rectF = New RectangleF(ptF.X - 35, ptF.Y - 35,
                                    70, 70)
    
            e.Graphics.FillEllipse(myB, rectF)
        Next
    End Using
    

    If you have other code to add Point data, like a Button click, after you add, change or remove data, use Invalidate to force a redraw: Me.Invaludate() is you are drawing to the form, or PictureBox1.Invalidate() if you are drawing over a control.

    The lesson is that now, every time the form needs to be repainted, your shapes will be redrawn as well.