Member Avatar for Micheal87

Hi, like title, I have a timer, that when reach 0 will fire event on another form, then timer restart but when reach 0 nothing happen. how can I achieve this?

 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        Dim value = CInt(Label10.Text)
        If value >= 1 And value <= 30 Then
            value -= 1.ToString
        Else
            If value >= 0 Then
                Form11.Button5_Click(sender, e)
                Timer1.Stop()
            End If
        End If
    End Sub

I can't say if it the main source of the problem, but the line If value >= 0 Then has the test reversed; it should be If value <= 0 Then instead.

This doesn't explain why it fails at exactly zero, but you'd be better off correcting it anyway.

Member Avatar for Micheal87

Hi, thank you for correction, also it's possible that the problem is because I installed visual studio 2022 ?
It's too soon for a stable version?

I'd want to seen the button5 event handler code but why not Form11.Button5.PerformClick() ?

Member Avatar for Micheal87

Sure, this is button5 click code, (Also I think I should put some already selected index by default, cause if use the button without selecting the first index give me the instance error because no index was selected. But I need this to do when the program is launched, and maybe saving changes)

Public Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
        For i = 0 To ComboBox3.Items.Count - 1
            ComboBox2.SelectedIndex = i
            Dim d As DateTime = DateTime.Now
            Dim parsedate As DateTime = ComboBox2.Items(i).ToString
            Dim d2 As DateTime = DateTime.ParseExact(parsedate, "dd/MM/yyyy HH:mm:ss", System.Globalization.CultureInfo.CurrentCulture)
            Dim dysdiff As Integer = (d - d2).Days
            ComboBox3.Items(i) = (365 - dysdiff).ToString + " Days"
        Next
    End Sub

The instance error is not unexpected so I take it you'll add code to handle this issue. Schol has already responded about that.

Also, since you don't use sender or e, why not Form.Button5_Click(null, null) or my first response idea.

Member Avatar for Micheal87

I'll try that thank you but, I don't know what happened but timer doesn't start anymore, I also checked that is enabled by default but when pressed the button doesn't work
the timer.tick event and button click is with the standard code
I also tried to unistall and reinstall Visual studio, and clean things with CCleaner + reboot of PC

Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        Dim value = CInt(Label10.Text)
        If value >= 1 And value <= 30 Then
            value -= 1.ToString
        Else
            If value <= 0 Then
               Form11.Button5.PerformClick()
                Timer1.Stop()
            End If
        End If
    End Sub

Long ago I learned to add the usual Timer1.Enabled() (remember I am not checking syntax here) and more to my form startup code.

That is, don't rely on defaults or what you see in the GUI. Set the status, time and enable as you see fit.

Also, you can put a breakpoint on that line two so you can query the state or Timer1.

Member Avatar for Micheal87

I put the breakpoint on the line, started the program, and clicked the button then the status is this, maybe the problem is the sender that send a string instead of a number ?

devenv_4VmJJEqPWx.png

I've supplied two other lines of code to click the button. At this point it's unclear what the issue is. But I see you made some progress on breakpoints so next step is a breakpoint for the timer handler.

Member Avatar for Micheal87

In the meanwhile I tried to create another button, timer, and this time the code I use was this

 Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        If Label11.Text >= "1" <= "30" Then
            Label11.Text = Label11.Text - 1.ToString
        ElseIf Label11.Text = "0" Then
            Form11.Button5.PerformClick()
            Timer2.Stop()
        End If
    End Sub

This one worked well, timer start normally, when reach 0 all the items, are updated like should, so I was thinking was there something wrong with CInt while converting the variable?
In any case the timer handler is the line of Private sub of timer1, I'm right?

If so, a breakpoint on the line in question and the following line to see what's going on.

Member Avatar for Micheal87

This is the breakpoint on the Cint line more in particulary this one

     Dim value = CInt(Label10.Text)

I saw there something really strange, because label10.text on form load is 30 like the other one, but then I noticed that the value cointain 0. How it's possible?

devenv_VtRkr22Zrz.png

Just as an aside, since you know that it is in the range 0..30, have you considered declaring value as Byte (and casting the string using CByte()) ? That would at least help eliminate one possible source of error (since you would never get a negative value).

Perhaps try writing a utility function to force saturation, like this (warning, untested code, it has been a while since I coded in VB.Net):

Public Function CByte_Saturate_Range(data As String, min As Byte, max As Byte) As Byte
    Dim value As Byte
    Dim swap As Byte

    If min = max Then
        Return min
    End If

    If min > max Then
        swap = min
        min = max 
        max = swap
    End If
     ' convert to a Short first, then force it to a positive absolute value
     ' before converting it to Byte
    value = CByte(Math.Abs(CShort(data))
    If min > value Then
         value = min
    ElseIf value > max Then
         value = max
    End If
    Return value
End Function

You would call it like so:

    value = CByte_Saturate_Range(Label10.Text, 0, 30)
    If value > 0 Then
        value = value - 1
    Else
        Form11.Button5.PerformClick()
        Timer1.Stop()
    End If
    label10.Text = CStr(value)

While this might seem overkill, it would at least separate the logic for converting and saturating the value from that of testing for the timer value.

Actually, let me back up a bit before I finish: why is the timer based on a Label's value in the first place? That might help us understand the wider goal involved.

Why not just supress the traling .toString and set value as an Integer?

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim value As Integer = CInt(Label10.Text)
        If value >= 1 And value <= 30 Then
            value -= 1
        Else
            If value <= 0 Then
                Form11.Button5.PerformClick()
                Timer1.Stop()
            End If
        End If
    End Sub
Member Avatar for Micheal87

@Schol-R-LEA
That solution seem great (I'm new to visual basic, but from your description, seem pretty good), the thing of the label value is because I was thinking for testing for see a number going down, for this I used Cint, in the first example. But if is any good any source to display a number (when I'm on testing mode).

@xrjf I will try it too

Both of these solution seem good.

Member Avatar for Micheal87

I tested both solutions.
@Schol-R-LEA solution working very good, also timer start on form load, which I prefer a lot.

@xrjf solution, doesn't start timer, like the value 0 on the breakpoint with the CInt

If needed a countdown you could do the following and get the countdown in Label10:

    Const maxVal As Integer = 30
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Try
            Dim value As Integer = maxVal ' default value 30 '
            Integer.TryParse(Label10.Text, value) ' if Label10 has a valid value assign it to value '
            If value >= 1 And value <= maxVal Then
                value -= 1
                Label10.Text = value.ToString
            Else
                If value <= 0 Then
                    Form11.Button5.PerformClick()
                    Timer1.Stop()
                    Label10.Text = maxVal.ToString
                End If
            End If
        Catch ex As Exception    
        End Try
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Label10.Text = maxVal.ToString
    End Sub
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.