Question How To Stop A Loop Until Key Is Pressed?

Coolbreeze78

Member
Joined
Mar 15, 2013
Messages
13
Programming Experience
1-3
I am fairly new to Visual Basic.Net and am working on a network simulator program to simulate packets being sent across a network. I do have experience in Java however but I couldn't get the code to do what I wanted so I switched to an easier language for GUIs.

My problem is that I have an array of circles that act as place holders on the screen, that I light up green when the packet is at that current location once the simulation is ran. I have a for loop that goes through the array and obtains the x,y coordinates of the current circle in the array.

What I am trying to do is, once the first circle is drawn green, wait for the user to press the space bar to continue execution and advance the loop to draw the next green circle. I have tried several ways of doing this by browsing the internet but I can't get it to work. I will past the code I have as well as the screenshot of the GUI to provide an idea of what I am trying to do.

Any help would be greatly appreciated as I am currently stuck and don't know what else to do besides work through my Visual Basic 2010 In 24 Hours book to try and learn as much as I can in hopes that I can apply that knowledge at a future time.

VB.NET:
Public Class NetworkSimulator


    Private intCircles(19, 2) As Integer
    Private flag As Boolean

    ' Create graphics object
    Dim g As Graphics

    Private Sub NetworkSimulator_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

        ' Create graphics
        g = Me.CreateGraphics

        ' Sizes
        Dim boxHeight, boxWidth, circleHeight, circleWidth, lboxX, rboxX, boxY, lcircleX, rcircleX, circleY As Integer
        boxHeight = 35
        boxWidth = 150
        circleHeight = 30
        circleWidth = 30

        ' Positions
        lboxX = 75
        rboxX = 782
        boxY = 75
        lcircleX = 30
        rcircleX = 941
        circleY = 75

        ' Populate the cirlces array
        intCircles(0, 0) = 30
        intCircles(0, 1) = 75
        intCircles(1, 0) = 30
        intCircles(1, 1) = 110
        intCircles(2, 0) = 30
        intCircles(2, 1) = 145
        intCircles(3, 0) = 30
        intCircles(3, 1) = 180
        intCircles(4, 0) = 30
        intCircles(4, 1) = 215
        intCircles(5, 0) = 30
        intCircles(5, 1) = 250
        intCircles(6, 0) = 30
        intCircles(6, 1) = 285

        ' Middle set
        intCircles(7, 0) = 70
        intCircles(7, 1) = 510
        intCircles(8, 0) = 255
        intCircles(8, 1) = 510
        intCircles(9, 0) = 512
        intCircles(9, 1) = 510
        intCircles(10, 0) = 739
        intCircles(10, 1) = 510
        intCircles(11, 0) = 924
        intCircles(11, 1) = 510

        ' Right set
        intCircles(12, 0) = 941
        intCircles(12, 1) = 75
        intCircles(13, 0) = 941
        intCircles(13, 1) = 110
        intCircles(14, 0) = 941
        intCircles(14, 1) = 145
        intCircles(15, 0) = 941
        intCircles(15, 1) = 180
        intCircles(16, 0) = 941
        intCircles(16, 1) = 215
        intCircles(17, 0) = 941
        intCircles(17, 1) = 250
        intCircles(18, 0) = 941
        intCircles(18, 1) = 285

        ' Draw circles
        Dim cX, cY As Integer
        Dim circlePen As New Pen(Color.Black, 2)

        For i As Integer = 0 To 18
            For j As Integer = 0 To 0
                cX = intCircles(i, j)
                j += 1
                cY = intCircles(i, j)

                g.DrawEllipse(Pens.Black, cX, cY, circleWidth, circleHeight)
            Next
            circleY += circleHeight + 5
        Next

        'Draw(Boxes)
        For index As Integer = 0 To 6
            g.DrawRectangle(Pens.Black, lboxX, boxY, boxWidth, boxHeight)
            g.DrawRectangle(Pens.Black, rboxX, boxY, boxWidth, boxHeight)
            g.FillRectangle(Brushes.LightGray, lboxX + 1, boxY + 1, boxWidth - 1, boxHeight - 1)
            g.FillRectangle(Brushes.LightGray, rboxX + 1, boxY + 1, boxWidth - 1, boxHeight - 1)
            boxY += boxHeight
        Next

        ' Set Font
        Dim objFont As Font
        objFont = New System.Drawing.Font("Arial Black", 8)

        ' Fill in Layer Text
        g.DrawString("Application Layer", objFont, System.Drawing.Brushes.Black, 97, 86)
        g.DrawString("Application Layer", objFont, System.Drawing.Brushes.Black, 804, 86)
        g.DrawString("Presentation Layer", objFont, System.Drawing.Brushes.Black, 95, 122)
        g.DrawString("Presentation Layer", objFont, System.Drawing.Brushes.Black, 802, 122)
        g.DrawString("Session Layer", objFont, System.Drawing.Brushes.Black, 107, 157)
        g.DrawString("Session Layer", objFont, System.Drawing.Brushes.Black, 814, 157)
        g.DrawString("Transport Layer", objFont, System.Drawing.Brushes.Black, 103, 192)
        g.DrawString("Transport Layer", objFont, System.Drawing.Brushes.Black, 810, 192)
        g.DrawString("Network Layer", objFont, System.Drawing.Brushes.Black, 107, 227)
        g.DrawString("Network Layer", objFont, System.Drawing.Brushes.Black, 814, 227)
        g.DrawString("Data Link Layer", objFont, System.Drawing.Brushes.Black, 104, 262)
        g.DrawString("Data Link Layer", objFont, System.Drawing.Brushes.Black, 811, 262)
        g.DrawString("Physical Layer", objFont, System.Drawing.Brushes.Black, 108, 297)
        g.DrawString("Physical Layer", objFont, System.Drawing.Brushes.Black, 815, 297)

        ' Draw display info box and input placeholder
        g.DrawRectangle(Pens.Black, 242, 75, 523, 245)
        g.DrawRectangle(Pens.Black, 242, 25, 523, boxHeight)
        g.FillRectangle(Brushes.LightGray, 243, 76, 522, 244)
        g.FillRectangle(Brushes.LightGray, 243, 26, 522, boxHeight - 1)

        ' Draw network cables
        g.DrawLine(Pens.Blue, 150, 320, 150, 397)
        g.DrawLine(Pens.Blue, 857, 320, 857, 397)
        g.DrawLine(Pens.Blue, 207, 450, 328, 450)
        g.DrawLine(Pens.Blue, 400, 450, 628, 450)
        g.DrawLine(Pens.Blue, 700, 450, 810, 450)

    End Sub

Private Sub btnInput_Click(sender As System.Object, e As System.EventArgs) Handles btnInput.Click

        ' Sizes
        Dim cX, cY, circleHeight, circleWidth As Integer
        circleHeight = 30
        circleWidth = 30

        ' Loop through the array when the user presses space and display the appropriate content
        For i As Integer = 0 To 18
            For j As Integer = 0 To 0
                cX = intCircles(i, j)
                j += 1
                cY = intCircles(i, j)

                ' Display a green circle over a black one
                g.FillEllipse(Brushes.Black, cX, cY, circleWidth, circleHeight)
                g.FillEllipse(Brushes.Lime, cX + 1, cY + 1, circleWidth - 2, circleHeight - 2)
            Next

            ' Display Data for the current layer

            ' Wait for user to press Space Bar
            flag = False
            Call Wait()


        Next
End Sub

Private Sub NetworkSimulator_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
    If e.KeyChar = Chr(32) Then
        flag = True
    End If
End Sub

Public Sub Wait()
    Do While flag = False
        Application.DoEvents()
    Loop
End Sub

End Class

Network.JPG
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,602
Location
Sydney, Australia
Programming Experience
10+
You wouldn't use a loop; it's that simple. You would handle the appropriate event to detect the key press and then advance the indicator one step and that's it. No loop.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,602
Location
Sydney, Australia
Programming Experience
10+
A lot of people tend to think of loops first if they want to do something repeatedly but loops are a "set and forget" type of thing. If you want interaction between each pair of steps then you don't want a loop.
 

Coolbreeze78

Member
Joined
Mar 15, 2013
Messages
13
Programming Experience
1-3
Ok I have modified the code but I am running into two other problems.

1.) My window graphics are flickering now when I move the mouse over the text box or the button for some reason.
2.) When I enter a string in the input box and then press Simulate, it should put a green circle in the first circle on the left. It does this, but as soon as I move the mouse off focus from the Simulate button (called btnInput in the code), the screen flickers again and the green circle disappears.

I am not sure what is causing this flickering because I don't have anything tied to mouse movements. The only thing I can figure is that the flicker has something to do with the focus on the text box and button, but I have no idea why as I haven't modified anything that would effect focus.

VB.NET:
Public Class NetworkSimulator

    ' Declare globals
    Private intCircles(19, 2) As Integer
    Private counter As Integer = 0
    Private circleHeight = 30
    Private circleWidth = 30
    Private input As String

    Private Sub NetworkSimulator_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

        ' Create graphics
        Dim g As Graphics
        g = Me.CreateGraphics

        ' Sizes
        Dim boxHeight, boxWidth, lboxX, rboxX, boxY, lcircleX, rcircleX, circleY As Integer
        boxHeight = 35
        boxWidth = 150

        ' Positions
        lboxX = 75
        rboxX = 782
        boxY = 75
        lcircleX = 30
        rcircleX = 941
        circleY = 75

        ' Populate the cirlces array
        intCircles(0, 0) = 30
        intCircles(0, 1) = 75
        intCircles(1, 0) = 30
        intCircles(1, 1) = 110
        intCircles(2, 0) = 30
        intCircles(2, 1) = 145
        intCircles(3, 0) = 30
        intCircles(3, 1) = 180
        intCircles(4, 0) = 30
        intCircles(4, 1) = 215
        intCircles(5, 0) = 30
        intCircles(5, 1) = 250
        intCircles(6, 0) = 30
        intCircles(6, 1) = 285

        ' Middle set
        intCircles(7, 0) = 70
        intCircles(7, 1) = 510
        intCircles(8, 0) = 255
        intCircles(8, 1) = 510
        intCircles(9, 0) = 512
        intCircles(9, 1) = 510
        intCircles(10, 0) = 739
        intCircles(10, 1) = 510
        intCircles(11, 0) = 924
        intCircles(11, 1) = 510

        ' Right set
        intCircles(12, 0) = 941
        intCircles(12, 1) = 75
        intCircles(13, 0) = 941
        intCircles(13, 1) = 110
        intCircles(14, 0) = 941
        intCircles(14, 1) = 145
        intCircles(15, 0) = 941
        intCircles(15, 1) = 180
        intCircles(16, 0) = 941
        intCircles(16, 1) = 215
        intCircles(17, 0) = 941
        intCircles(17, 1) = 250
        intCircles(18, 0) = 941
        intCircles(18, 1) = 285

        ' Draw circles
        Dim cX, cY As Integer

        For i As Integer = 0 To 18
            For j As Integer = 0 To 0
                cX = intCircles(i, j)
                j += 1
                cY = intCircles(i, j)

                g.FillEllipse(Brushes.Black, cX, cY, circleWidth, circleHeight)
                g.FillEllipse(Brushes.White, cX + 2, cY + 2, circleWidth - 4, circleHeight - 4)
            Next
            circleY += circleHeight + 5
        Next

        ' Set up a pen with a 2 pixel width
        Dim objBorderPen As Pen
        objBorderPen = New Pen(Drawing.Color.Black, 2)

        'Draw(Boxes)
        For index As Integer = 0 To 6
            g.DrawRectangle(objBorderPen, lboxX, boxY, boxWidth, boxHeight)
            g.DrawRectangle(objBorderPen, rboxX, boxY, boxWidth, boxHeight)
            g.FillRectangle(Brushes.LightGray, lboxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2)
            g.FillRectangle(Brushes.LightGray, rboxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2)
            boxY += boxHeight
        Next

        ' Set Font
        Dim objFont As Font
        objFont = New System.Drawing.Font("Arial Black", 8)

        ' Fill in Layer Text
        g.DrawString("Application Layer", objFont, System.Drawing.Brushes.Black, 97, 86)
        g.DrawString("Application Layer", objFont, System.Drawing.Brushes.Black, 804, 86)
        g.DrawString("Presentation Layer", objFont, System.Drawing.Brushes.Black, 95, 122)
        g.DrawString("Presentation Layer", objFont, System.Drawing.Brushes.Black, 802, 122)
        g.DrawString("Session Layer", objFont, System.Drawing.Brushes.Black, 107, 157)
        g.DrawString("Session Layer", objFont, System.Drawing.Brushes.Black, 814, 157)
        g.DrawString("Transport Layer", objFont, System.Drawing.Brushes.Black, 103, 192)
        g.DrawString("Transport Layer", objFont, System.Drawing.Brushes.Black, 810, 192)
        g.DrawString("Network Layer", objFont, System.Drawing.Brushes.Black, 107, 227)
        g.DrawString("Network Layer", objFont, System.Drawing.Brushes.Black, 814, 227)
        g.DrawString("Data Link Layer", objFont, System.Drawing.Brushes.Black, 104, 262)
        g.DrawString("Data Link Layer", objFont, System.Drawing.Brushes.Black, 811, 262)
        g.DrawString("Physical Layer", objFont, System.Drawing.Brushes.Black, 108, 297)
        g.DrawString("Physical Layer", objFont, System.Drawing.Brushes.Black, 815, 297)

        ' Draw display info box and input placeholder
        g.DrawRectangle(objBorderPen, 242, 75, 523, 245)
        g.DrawRectangle(objBorderPen, 242, 25, 523, boxHeight)
        g.FillRectangle(Brushes.LightGray, 243, 76, 521, 243)
        g.FillRectangle(Brushes.LightGray, 243, 26, 521, boxHeight - 2)

        ' Draw network cables
        g.DrawLine(Pens.Blue, 150, 320, 150, 397)
        g.DrawLine(Pens.Blue, 857, 320, 857, 397)
        g.DrawLine(Pens.Blue, 207, 450, 328, 450)
        g.DrawLine(Pens.Blue, 400, 450, 628, 450)
        g.DrawLine(Pens.Blue, 700, 450, 810, 450)

        g.Dispose()

    End Sub

    Private Sub btnInput_Click(sender As System.Object, e As System.EventArgs) Handles btnInput.Click

        ' Get the string
        input = txtInput.Text

        ' Advance the packet
        counter = AdvancePos(counter)

        ' Reset the input box
        txtInput.Text = ""

    End Sub

    Private Function AdvancePos(ByVal pos As Integer) As Integer

        ' Sizes
        Dim cX, cY, j As Integer
        j = 0

        If input <> "" Then

            ' Create graphics
            Dim g As Graphics
            g = Me.CreateGraphics

            ' Get the x and y position of the packet
            cX = intCircles(pos, j)
            j += 1
            cY = intCircles(pos, j)

            ' Is there a previous position
            If pos > 0 Then

                ' Remove the green circle
                g.FillEllipse(Brushes.Black, cX, cY, circleWidth, circleHeight)
                g.FillEllipse(Brushes.Lime, cX + 2, cY + 2, circleWidth - 4, circleHeight - 4)

            End If

            ' Advance the position of current
            pos += 1

            ' Check the new position to make sure it doesn't go past position 18
            If pos < 19 Then

                ' Set the green circle in the next position
                g.FillEllipse(Brushes.Black, cX, cY, circleWidth, circleHeight)
                g.FillEllipse(Brushes.Lime, cX + 2, cY + 2, circleWidth - 4, circleHeight - 4)

            Else

                ' Reset the current position to 0
                pos = 0

            End If

            g.Dispose()

        End If

        ' Return the new current position
        Return pos

    End Function

End Class
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,602
Location
Sydney, Australia
Programming Experience
10+
First things first, you should pretty much NEVER be calling CreateGraphics. The Paint event provides a Graphics object for you so use that. Secondly, why use GDI+ for that at all? I strongly recommend getting rid of all that code and just using Labels and PictureBoxes. You can use a PictureBox for each circle and just swap the Image from an empty circle to a filled circle each time you need a change.
 

Coolbreeze78

Member
Joined
Mar 15, 2013
Messages
13
Programming Experience
1-3
I am still fairly new to programming so there is a lot I don't know or understand. I was using the CreateGraphics because it was shown in this book I have. I don't know where or how to use the paint object.

And I guess that makes sense, I will switch out the drawing for picture boxes. I didn't know I could draw in a picture box before so that's why I drew everything by hand.
 

Coolbreeze78

Member
Joined
Mar 15, 2013
Messages
13
Programming Experience
1-3
Ok, I just used a snipping tool to pull the images I drew and save them as a jpg. So the almost everything but the network lines have been replaced with picture boxes.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,602
Location
Sydney, Australia
Programming Experience
10+
I am still fairly new to programming so there is a lot I don't know or understand. I was using the CreateGraphics because it was shown in this book I have. I don't know where or how to use the paint object.
Unfortunately, a lot of those who purport to teach do so very poorly and often take the easy option. There are many GDI+ examples around that use CreateGrpahics and that is very bad. If they were to provide the caveat that that is only done to get a Graphics object but you should never do that in practice then it might be OK but otherwise it's just poor.

There is no Paint object. It's the Paint event of the control you want to draw on and, like all events, the handler receives two arguments: one the object that raised the event and the other the data for the event. In the case of the Paint event, the Graphics object is part of that data. You should read the documentation for the Paint event to see how it works.
 

Coolbreeze78

Member
Joined
Mar 15, 2013
Messages
13
Programming Experience
1-3
Ok, I just used a snipping tool to pull the images I drew and save them as a jpg. So the almost everything but the network lines have been replaced with picture boxes.

I also have a counter to keep track of the current position. But I am not sure how to send this information to the function to advance the circle position. For instance I was thinking of sending the current position in a variable to the function like pos = 2. Then when I get it in, use another variable to store the name of the next picture box. Like pos += 1, then strCircle = "picCircle" & pos. But then if I were to try and call the control image method I don't think this will work. Like strCircle.Image = My.Resources.circleGreen.

Anyway, I took the long approach and just did if statements for each scenario. Current code is below. And yeah, I feel bad for whoever hires me after my degree because they haven't really taught me all that much in computer science.

VB.NET:
Public Class NetworkSimulator

    ' Declare globals
    Private counter As Integer = 0
    Private input As String

    Private Sub NetworkSimulator_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyCode = Keys.Space Then
            ' Advance the packet
            counter = AdvancePos(counter)
        End If
    End Sub

    Private Sub NetworkSimulator_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

        ' Create graphics
        Dim g As Graphics
        g = Me.CreateGraphics

        ' Draw network cables
        g.DrawLine(Pens.Blue, 150, 320, 150, 397)
        g.DrawLine(Pens.Blue, 857, 320, 857, 397)
        g.DrawLine(Pens.Blue, 207, 450, 328, 450)
        g.DrawLine(Pens.Blue, 400, 450, 628, 450)
        g.DrawLine(Pens.Blue, 700, 450, 810, 450)

        g.Dispose()

    End Sub

    Private Sub btnInput_Click(sender As System.Object, e As System.EventArgs) Handles btnInput.Click

        ' Get the string
        input = txtInput.Text

        ' Advance the packet
        counter = AdvancePos(counter)

        ' Reset the input box
        txtInput.Text = ""

    End Sub

    Private Function AdvancePos(ByVal pos As Integer) As Integer

        If input <> "" Then

            ' Is this a new packet, if so start at position 0
            If pos = 0 Then

                ' Swap the image
                picCircle0.Image = My.Resources.CircleGreen

            ' If this is a current packet, advance the position
            Else
                ' Advance the position of current
                pos += 1

                ' Check the new position to make sure it doesn't go past position 18
                If pos < 19 Then

                    If pos = 1 Then

                        ' Swap the previous circle
                        picCircle0.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle1.Image = My.Resources.CircleGreen

                    ElseIf pos = 2 Then

                        ' Swap the previous circle
                        picCircle1.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle2.Image = My.Resources.CircleGreen

                    ElseIf pos = 3 Then

                        ' Swap the previous circle
                        picCircle2.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle3.Image = My.Resources.CircleGreen

                    ElseIf pos = 4 Then

                        ' Swap the previous circle
                        picCircle3.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle4.Image = My.Resources.CircleGreen

                    ElseIf pos = 5 Then

                        ' Swap the previous circle
                        picCircle4.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle5.Image = My.Resources.CircleGreen

                    ElseIf pos = 6 Then

                        ' Swap the previous circle
                        picCircle6.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle7.Image = My.Resources.CircleGreen

                    ElseIf pos = 7 Then

                        ' Swap the previous circle
                        picCircle6.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle7.Image = My.Resources.CircleGreen

                    ElseIf pos = 8 Then

                        ' Swap the previous circle
                        picCircle7.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle8.Image = My.Resources.CircleGreen

                    ElseIf pos = 9 Then

                        ' Swap the previous circle
                        picCircle8.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle9.Image = My.Resources.CircleGreen

                    ElseIf pos = 10 Then

                        ' Swap the previous circle
                        picCircle9.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle10.Image = My.Resources.CircleGreen

                    ElseIf pos = 11 Then

                        ' Swap the previous circle
                        picCircle10.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle11.Image = My.Resources.CircleGreen

                    ElseIf pos = 12 Then

                        ' Swap the previous circle
                        picCircle11.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle12.Image = My.Resources.CircleGreen

                    ElseIf pos = 13 Then

                        ' Swap the previous circle
                        picCircle12.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle13.Image = My.Resources.CircleGreen

                    ElseIf pos = 14 Then

                        ' Swap the previous circle
                        picCircle13.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle14.Image = My.Resources.CircleGreen

                    ElseIf pos = 15 Then

                        ' Swap the previous circle
                        picCircle14.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle15.Image = My.Resources.CircleGreen

                    ElseIf pos = 16 Then

                        ' Swap the previous circle
                        picCircle15.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle16.Image = My.Resources.CircleGreen

                    ElseIf pos = 17 Then

                        ' Swap the previous circle
                        picCircle16.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle17.Image = My.Resources.CircleGreen

                    ElseIf pos = 18 Then

                        ' Swap the previous circle
                        picCircle17.Image = My.Resources.CircleClear
                        ' Swap the current circle
                        picCircle18.Image = My.Resources.CircleGreen

                    End If

                Else
                    ' Reset the current position to 0
                    pos = 0

                End If
            End If
        End If

        ' Return the new current position
        Return pos

    End Function

End Class
 
Top Bottom