-2

This is what I have so far

Private Sub BtnAnswerA_Clicked(sender As Object, e As EventArgs) Handles btnAnswerA.Click
    Me.btnAnswerA.BackColor = Color.Green
    System.Threading.Thread.Sleep(10000)
    Me.Hide()
    Q2.Show()
End Sub

I want, when button is clicked, it will change color. Then, 10 seconds later it will open another form. But it waits for 10 seconds before opening next form without changing the color.

T.S.
  • 18,195
  • 11
  • 58
  • 78

2 Answers2

1

At a guess, you might want to show other forms and perhaps with differing delays. You can do that with a Sub that takes the form and delay as parameters.

Assuming you are using VS2010 or later, your code could look something like this:

Private Sub ShowNextForm(formToShow As Form, secondsDelay As Double)
    Dim tim As New System.Windows.Forms.Timer
    tim.Interval = CInt(secondsDelay * 1000)
    tim.Start()
    AddHandler tim.Tick, Sub(sender As Object, e As EventArgs)
                             tim.Stop()
                             tim.Dispose()
                             Me.Hide()
                             formToShow.Show()
                         End Sub
End Sub

Private Sub btnAnswerA_Click(sender As Object, e As EventArgs) Handles btnAnswerA.Click
    Dim bn = DirectCast(sender, Button)
    bn.Enabled = False
    bn.BackColor = Color.Green
    Dim nextForm As New Q2
    ShowNextForm(nextForm, 10)

End Sub

Then if you had another button which you wanted to do the same thing, say "btnAnswer99" with a form z99 and a delay of 2.5 seconds, you would only need to write the code

Private Sub btnAnswer99_Click(sender As Object, e As EventArgs) Handles btnAnswer99.Click
    Dim bn = DirectCast(sender, Button)
    bn.Enabled = False
    bn.BackColor = Color.Blue
    Dim nextForm As New z99
    ShowNextForm(nextForm, 2.5)

End Sub

Getting a bit more advanced... maybe something to look at later...

You may notice that you are repeating a lot of code for each button. At this point it would be time to consider refactoring your code so that you write the essential code only once, and have parameters which determine what it does.

So you look at what is common between all the button click handlers, such as they all have a form they are on, a form to show, some BackColor to change to, and a delay until the next form is shown, and of course that they refer to a button.

This is an ideal opportunity to create a Class to encapsulate all the parts, perhaps a bit like this:

Friend Class SetButtonToShowForm

    Property thisForm As Form
    Property nextForm As Form
    Property buttonRef As Button
    Property buttonBackColor As Color
    Property secondsDelay As Double

    Friend Sub ShowNextForm(currentForm As Form, formToShow As Form, secondsDelay As Double)
        Dim tim As New System.Windows.Forms.Timer
        tim.Interval = CInt(secondsDelay * 1000)
        tim.Start()
        AddHandler tim.Tick, Sub(sender As Object, e As EventArgs)
                                 tim.Stop()
                                 tim.Dispose()
                                 currentForm.Hide()
                                 formToShow.Show()
                             End Sub

    End Sub

    Friend Sub bnClick(sender As Object, e As EventArgs)
        Dim bn = DirectCast(sender, Button)
        bn.Enabled = False
        bn.BackColor = Me.buttonBackColor

        ShowNextForm(thisForm, nextForm, secondsDelay)

    End Sub

    Public Sub New()
        ' empty constructor
    End Sub

    Public Sub New(sourceForm As Form, targetForm As Form, buttonRef As Button, backColor As Color, secondsDelay As Double)
        Me.thisForm = sourceForm
        Me.nextForm = targetForm
        Me.buttonRef = buttonRef
        Me.buttonBackColor = backColor
        Me.secondsDelay = secondsDelay
        AddHandler Me.buttonRef.Click, AddressOf bnClick

    End Sub

End Class

and then you could set up all the buttons in one procedure along the lines of

Private Sub SetButtonHandlers()
    Dim b1 As New SetButtonToShowForm(Me, Q2, btnAnswerA, Color.Green, 5)
    Dim b2 As New SetButtonToShowForm(Me, z99, btnAnswer99, Color.Blue, 2.3)
End Sub

So you can see that with a little bit more effort, you can make it much easier to set up more buttons.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • It is funny even that you spend so much time on this when poor guy has it working with `DoEvents` – T.S. Mar 11 '16 at 00:25
-3

See in code

Private Sub BtnAnswerA_Clicked(sender As Object, e As EventArgs) Handles btnAnswerA.Click
    Me.btnAnswerA.BackColor = Color.Green
    Application.DoEvents()   ' <--- THERE
    System.Threading.Thread.Sleep(10000)
    Me.Hide()
    Q2.Show()
End Sub

What happens, whatever happens, happens so fast, your form/button has no time to repaint. In these cases you use DoEvents to tell app to finish all the messages in the queue before handling next one. It finishes painting and then it starts sleeping, hence showing a green button.

DoEvents brings opinions. I like this one https://stackoverflow.com/a/5183623/1704458

People are so offended by DoEvents, but it never failed me. Ok. Here is what I am writing for @Plutonix

private _timer As new System.Timers.Timer(10000)
Private Sub Form_Load(sender As Object, e As EventArgs)
    AddHandler _timer.Elapsed, AddressOf OnElapsed
End Sub

Private Sub BtnAnswerA_Clicked(sender As Object, e As EventArgs) Handles btnAnswerA.Click
    Me.btnAnswerA.BackColor = Color.Green
    Me.btnAnswerA.Enabled = False
    _timer.Enabled = True 
End Sub

Private Sub OnElapsed (sender As Object, e As ElapsedEventArgs)
    _timer.Enabled = False 
    Me.btnAnswerA.Enabled = True
    Me.Hide()
    Q2.Show()
End Sub

Timer Elapsed runs on different thread, so your form will be responsive instead of frozen

Community
  • 1
  • 1
T.S.
  • 18,195
  • 11
  • 58
  • 78
  • @T.S. I can find no documentation that suggests that a Windows.Forms.Timer uses a separate thread. The documentation for [Windows.Forms.Timer Class](https://msdn.microsoft.com/en-us/library/system.windows.forms.timer%28v=vs.110%29.aspx) specifically states "This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing." (Sorry, I don't mean to be unkind to you, but you are writing things which are *wrong*.) – Andrew Morton Mar 10 '16 at 22:24
  • @AndrewMorton you're confused. My example is using `System.Timers.Timer`. And here is MSDN: *The event-handling method might run on one thread at the same time that another thread calls the Stop method...* which means that command `Stop` can come from a different thread than a thread on which `Elapsed` runs. Here: http://www.albahari.com/threading/part3.aspx - search for **Multithreaded Timers** – T.S. Mar 10 '16 at 23:39