Why don't all my ellipses show ?

Poppa Mintin

Well-known member
Joined
Jan 4, 2018
Messages
45
Programming Experience
10+
Hi,

I'm trying to draw 36 dots on my windows form 1. For the purpose of this question I've increased the size of the dots to be much larger circular ellipses.

Image1.png

Here is Form1. Clicking 'Dots' ought to draw 36 'dots' on the form in 6 rows of 6 columns, to form the corners of 25 boxes in a 5 x 5 grid.

Here is the code:
VB.NET:
Public Class Form1

    Dim box, col, row, sptX, sptY As Int32
    Dim pen1 As Pen = New Pen(Color.Black, 1)
    Dim sldBsh As New SolidBrush(Color.Black)
    Dim gObjet As Drawing.Graphics = Me.CreateGraphics()

    Private Sub Form1_Load() Handles MyBase.Load
        Button1.Text = "EXIT"
        Button2.Text = "Dots"
        Initialise()
    End Sub

    Private Sub B1_Click() Handles Button1.Click
        Application.Exit()
    End Sub


    Private Sub B2_Click() Handles Button2.Click
        Dots()
    End Sub

    Public Sub Initialise()
        Dim meX, meY As Int32, Scn As Screen = Screen.AllScreens(0)
        '   AllScreens(0): 0 = THIS screen, others are 1, 2 etc.

        '   Setup Form1 size and position.
        col = 5
        row = 5
        box = CInt(Scn.Bounds.Width / (col + 10)) '  Square box size.
        Me.Width = box * (col + 1)
        Me.Height = CInt(box * (row + 1)) + Button1.Height
        meX = CInt((Scn.Bounds.Width - Me.Width) * 0.5)
        meY = CInt((Scn.Bounds.Height - Me.Height) * 0.5)
        Me.Location = New Point(meX, meY)

        '   Setup variables.
        Label1.Text = CInt(col * row).ToString & " boxes"
        Me.Show()
    End Sub

    Private Sub Dots()
        '   Draw spots.
        sptY = CInt(box / 2)
        For i = 0 To col
            sptX = CInt(box / 2)     'col
            For j = 0 To row
                Dim rect As Rectangle = New Rectangle(sptX, sptY, 60, 60)
                gObjet.FillEllipse(sldBsh, rect)
                sptX += box
            Next
            sptY += box    'row
        Next
    End Sub

End Class
Clicking 'Dots' actually produces: -

Image2.png

All the maths works out correctly when viewed stepped through from a breakpoint. I have used several different options of numbers of 'Boxes', 5x5, 5x10, 10x10, 15x10. All exhibit this strange result, just a small area drawn to.

I can't find anything which might cause this in the properties dialogue, which confirms that there are only 2 Buttons and a Label on the form. The borders are set to 'None' but trying other options makes no difference.

I'm at a loss to understand what's going on.



Poppa.

VS 2017 Community Version 15.5.5.
Windows 10. from initial install.
Intel i7 machine.
 
Me.CreateGraphics()
Mistake, use e.Graphics in Paint event when you draw.
 
I can't find how to do that.

The MSDN examples that I find WRT e.Graphics all say to use: -
VB.NET:
ByVal e As PaintEventArgs
So I've tried that but then I get an error saying 'e is not declared' which is true, but I can't find how to declare it.

For example I tried modifying the previous code thus: -
VB.NET:
    Private Sub Dots(ByVal e As PaintEventArgs)
        '   Draw spots.
        sptY = CInt(box / 2)
        For i = 0 To col
            sptX = CInt(box / 2)     'col
            For j = 0 To row
                Dim rect As Rectangle = New Rectangle(sptX, sptY, 60, 60)
                e.Graphics.FillEllipse(sldBsh, rect)
                sptX += box
            Next
            sptY += box    'row
        Next
    End Sub
Now I don't get any error messages about the Dots subroutine.

However: -
VB.NET:
    Private Sub B2_Click() Handles Button2.Click
        Dots()
    End Sub
Button2.Click's call to ' Sub Dots() ' now needs a Paint Event Argument of course, and I can't find what it needs that doesn't get an error message.


Poppa.
 
Last edited:
Select the form in Designer and use the Properties window to find the Paint event, doubleclick it to generate the event handler.
 
Sorry, I'm still floundering...
I have this code...
VB.NET:
    Private Sub F1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint


    End Sub
...but I can't find what to do with it !

I can't find how to call 'Dots'.


Poppa.

PS.
It's gone 02.00 here in the UK, I'll try again tomorrow... (Well... later this morning! :D )
 
Last edited:
As suggested, all GDI+ drawing should be done in the Paint event handler (or possibly the OnPaint method, which raises that event) for the control being drawn on. Note that a form is a control. The steps are simple:

1. Store all the data required to describe your drawing in member variables.
2. Handle the Paint event of the appropriate control, access the data from step 1 and draw using e.Graphics.
3. Any time the data representing the drawing changes, invalidate the are that has changed.

With regards to step 3, you can force an immediate total repaint of a control by calling its Refresh method. Internally, Refresh calls Invalidate with no parameters and Update. Invalidate is what tells the control what area needs to be repainted (no parameters means the whole control) and Update forces the invalidated area to be immediately repainted. Usually, it is enough to simply call Invalidate and let the control repaint when it wants to, which will generally be very soon after anyway.

When calling Invalidate, it is generally preferable to specify the smallest are reasonably possible to be repainted. That's because the actual repainting is the slowest part of the process. You can call Invalidate multiple times to specify multiple areas.

In your case, if you have a method that does the drawing then that method should have a parameter of type Graphics and you can then call that method from the Paint event handler and pass e.Graphics as an argument.
 
Thanks guys,

I have it fixed. Woke up this morning with the answer in mind, not quite right but John's explanation sorted that out.

Integer division is neat too... Thanks John.



Poppa.
 
Back
Top