Archief - [VB.NET] Hoe de timerfunctie gebruiken.

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

R009

Legacy Member
Ik ben bezig met een programma te schrijven. Ik heb 3 textvakken waar de gebruiker zijn uren, minuten en seconden moet invullen. Een timer moet dan aftellen tot alle textvakken ( of labels) op 0 staan.

Nu weet ik niet hoe ik de Timer kan forceren om ook rekening te houden met uren, minuten en seconden. Heeft er iemand enige suggesties?

Raanº³

Legacy Member
Een mogelijke manier is om je uren en minuten eerst om te zetten naar seconden.

1 timer = cntCounter; de interval op 1000 ms gezet
3 textboxen: txtHours, txtMinutes, txtSeconds
1 knop om te starten: btnGo
1 label voor resultaat: lblResult
Code:
    Private Sub cntCounter_Tick(sender As System.Object, e As System.EventArgs) Handles cntCounter.Tick
        Dim lngSecondsToTick As Long = GetSecondsFromTextBox()

        lngSecondsToTick -= 1
        lblResult.Text = "Nog " + lngSecondsToTick.ToString() + " seconden te gaan!"

        WriteToTextBoxes(GetCountdownFromSeconds(lngSecondsToTick))

        If lngSecondsToTick = 0 Then
            lblResult.Text = "'t is gedaan!"
            cntCounter.Stop()
        End If


    End Sub

    Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        cntCounter.Start()
    End Sub
    Private Function GetSecondsFromTextBox() As Long
        'Result in Seconden
        Dim lngResult As Long = 0

        lngResult = CType(txtSeconds.Text, Long)
        lngResult += (CType(txtMinutes.Text, Long) * 60)
        lngResult += (CType(txtHours.Text, Long) * 3600)

        Return lngResult

    End Function
    Private Function GetCountdownFromSeconds(ByVal lngSeconds As Long) As Long()
        Dim lngResult(2) As Long

        Dim lngInput As Long = lngSeconds
        'Onze buffer om weg te schrijven
        Dim lngBuffer As Long = 0

        'Eerst onze uren
        lngBuffer = lngInput \ 3600
        lngResult(0) = lngBuffer
        lngInput -= lngBuffer * 3600

        'Dan onze minuten aftrekken
        lngBuffer = lngInput \ 60
        lngResult(1) = lngBuffer
        lngInput -= lngBuffer * 60

        'Niets nodig, indien alles goed is gegaan, hebben we automatisch de seconden resterend in onze lngInput
        lngResult(2) = lngInput

        Return lngResult
    End Function
    Private Sub WriteToTextBoxes(ByVal lngSeconds() As Long)
        txtHours.Text = lngSeconds(0).ToString()
        txtMinutes.Text = lngSeconds(1).ToString()
        txtSeconds.Text = lngSeconds(2).ToString()

    End Sub

Wat je zou 'kunnen' doen is 2 functies schrijven:
1 functie die je uren en minuten converteert naar totale seconden
en 1 functie met als input de totale seconden die een array terug geeft met 3 elementen: uren, minuten en seconden.

Natuurlijk deploy deze code niet niet klakkeloos -- zorg voor Quality Control & Error handling.

R009

Legacy Member
Raanº³ zei:
Een mogelijke manier is om je uren en minuten eerst om te zetten naar seconden.

1 timer = cntCounter; de interval op 1000 ms gezet
3 textboxen: txtHours, txtMinutes, txtSeconds
1 knop om te starten: btnGo
1 label voor resultaat: lblResult
Code:
    Private Sub cntCounter_Tick(sender As System.Object, e As System.EventArgs) Handles cntCounter.Tick
        Dim lngSecondsToTick As Long = GetSecondsFromTextBox()

        lngSecondsToTick -= 1
        lblResult.Text = "Nog " + lngSecondsToTick.ToString() + " seconden te gaan!"

        WriteToTextBoxes(GetCountdownFromSeconds(lngSecondsToTick))

        If lngSecondsToTick = 0 Then
            lblResult.Text = "'t is gedaan!"
            cntCounter.Stop()
        End If


    End Sub

    Private Sub btnGo_Click(sender As System.Object, e As System.EventArgs) Handles btnGo.Click
        cntCounter.Start()
    End Sub
    Private Function GetSecondsFromTextBox() As Long
        'Result in Seconden
        Dim lngResult As Long = 0

        lngResult = CType(txtSeconds.Text, Long)
        lngResult += (CType(txtMinutes.Text, Long) * 60)
        lngResult += (CType(txtHours.Text, Long) * 3600)

        Return lngResult

    End Function
    Private Function GetCountdownFromSeconds(ByVal lngSeconds As Long) As Long()
        Dim lngResult(2) As Long

        Dim lngInput As Long = lngSeconds
        'Onze buffer om weg te schrijven
        Dim lngBuffer As Long = 0

        'Eerst onze uren
        lngBuffer = lngInput \ 3600
        lngResult(0) = lngBuffer
        lngInput -= lngBuffer * 3600

        'Dan onze minuten aftrekken
        lngBuffer = lngInput \ 60
        lngResult(1) = lngBuffer
        lngInput -= lngBuffer * 60

        'Niets nodig, indien alles goed is gegaan, hebben we automatisch de seconden resterend in onze lngInput
        lngResult(2) = lngInput

        Return lngResult
    End Function
    Private Sub WriteToTextBoxes(ByVal lngSeconds() As Long)
        txtHours.Text = lngSeconds(0).ToString()
        txtMinutes.Text = lngSeconds(1).ToString()
        txtSeconds.Text = lngSeconds(2).ToString()

    End Sub

Wat je zou 'kunnen' doen is 2 functies schrijven:
1 functie die je uren en minuten converteert naar totale seconden
en 1 functie met als input de totale seconden die een array terug geeft met 3 elementen: uren, minuten en seconden.

Natuurlijk deploy deze code niet niet klakkeloos -- zorg voor Quality Control & Error handling.

Tuurlijk moet daar nog wat error handling bij zitten. Anders kan er nog veel fout lopen. Zoals cptKangaroo al zegt kan je dat mooi opvangen met een Masked Textbox.
Ik heb nog wel een vraag over je code? waarom gebruik je eigenlijk een soort buffer?

Raanº³

Legacy Member
Je zou het zonder 'buffer' ook kunnen doen, maar heb in dit geval de code zo geschreven dat deze leesbaar en logisch eruit ziet :)

Wat je nodig hebt zijn minstens 2 variabelen:
Je wilt weten hoeveel uren/minuten/seconden er zijn (h/m/s)
En je wilt de resterende ticks weten. (y)

Ik persoonlijk ben van mening dat lngResult output is, en output gebruik je niet om nog berekeningen mee uit te voeren ;) Daarom dat ik voor een hulpvariabele (z) heb gekozen welke eerst de respectievelijke uren/minuten filtert (en wegschrijft naar onze output) en daarna deze in vermindering brengt van de totale resterende ticks.

y = totale ticks

'Hier doen we uren
' 1 uur = 60 minuten
' 1 minuut = 60 seconden
' 1 uur = 60 * 60
' 1 uur = 3600
' \ is integer divisie, we willen namelijk niet weten wat er na de komma komt maar we willen de totale gehelen (uren/minuten) uit onze resterende ticks halen
' y -= z is synoniem voor y = y - z
z = y \ 3600
h = z
y -= z

'Volgende op de lijst: minuten, onze uren zijn er al uitgefilterd
' 1 minuut = 60 seconden
z = y \ 60
m = z
y -= z

'nu komen de seconden
'echter: 1 tick = 1 seconde
'en we hebben alle grotere variabelen er al uit gefilterd, dus dit getal is zowiezo kleiner dan 60 (1 minuut)
s = z

cptKangaroo

Legacy Member
Een TimeSpan is gemaakt om allerlei tijdsbewerkingen te doen, dus misschien is het makkelijker om je programma daarrond op te bouwen.

R009

Legacy Member
Raanº³ zei:
Je zou het zonder 'buffer' ook kunnen doen, maar heb in dit geval de code zo geschreven dat deze leesbaar en logisch eruit ziet :)

Wat je nodig hebt zijn minstens 2 variabelen:
Je wilt weten hoeveel uren/minuten/seconden er zijn (h/m/s)
En je wilt de resterende ticks weten. (y)

Ik persoonlijk ben van mening dat lngResult output is, en output gebruik je niet om nog berekeningen mee uit te voeren ;) Daarom dat ik voor een hulpvariabele (z) heb gekozen welke eerst de respectievelijke uren/minuten filtert (en wegschrijft naar onze output) en daarna deze in vermindering brengt van de totale resterende ticks.

y = totale ticks

'Hier doen we uren
' 1 uur = 60 minuten
' 1 minuut = 60 seconden
' 1 uur = 60 * 60
' 1 uur = 3600
' \ is integer divisie, we willen namelijk niet weten wat er na de komma komt maar we willen de totale gehelen (uren/minuten) uit onze resterende ticks halen
' y -= z is synoniem voor y = y - z
z = y \ 3600
h = z
y -= z

'Volgende op de lijst: minuten, onze uren zijn er al uitgefilterd
' 1 minuut = 60 seconden
z = y \ 60
m = z
y -= z

'nu komen de seconden
'echter: 1 tick = 1 seconde
'en we hebben alle grotere variabelen er al uit gefilterd, dus dit getal is zowiezo kleiner dan 60 (1 minuut)
s = z

Dan kan ik eigenlijk die lijn van logica doortrekken om er de dagen bij te voegen...

R009

Legacy Member
cptKangaroo zei:
Een TimeSpan is gemaakt om allerlei tijdsbewerkingen te doen, dus misschien is het makkelijker om je programma daarrond op te bouwen.

ziet er een krachtige functie uit. Ben eigenlijk blij dat ik iets meer kan leren over tijdsberekeningen in een programma. Want tijd is een vies ding :p

Raanº³

Legacy Member
R009 zei:
Dan kan ik eigenlijk die lijn van logica doortrekken om er de dagen bij te voegen...

Yep, maar als je met 'dagen' zou werken, zou ik het niet implementeren zoals ik het neergeschreven heb. Zoals ik het geschreven had, doe je een tick, slaap je de resterende tijd van de 1000 ms en doe je dan weer een tick. Bij elke tick voer je je code uit. Niet echt efficient te noemen als je dit dagen aan een stuk zou aanhouden.

Wat ik begrepen had, is dat je een soort countdown wou? Je geeft het aantal uren/minuten/seconden in de toekomst dat je countdown zou aflopen en elke seconde trek je daar 1 van af?

Ik denk dat je je vraag eens anders gaat moeten uitleggen, zeker aangezien je interesse hebt in een timespan, welke dient voor berekeningen tussen 2 datums te doen (en niet voor een countdown).

R009

Legacy Member
Raanº³ zei:
Yep, maar als je met 'dagen' zou werken, zou ik het niet implementeren zoals ik het neergeschreven heb. Zoals ik het geschreven had, doe je een tick, slaap je de resterende tijd van de 1000 ms en doe je dan weer een tick. Bij elke tick voer je je code uit. Niet echt efficient te noemen als je dit dagen aan een stuk zou aanhouden.

Wat ik begrepen had, is dat je een soort countdown wou? Je geeft het aantal uren/minuten/seconden in de toekomst dat je countdown zou aflopen en elke seconde trek je daar 1 van af?

Ik denk dat je je vraag eens anders gaat moeten uitleggen, zeker aangezien je interesse hebt in een timespan, welke dient voor berekeningen tussen 2 datums te doen (en niet voor een countdown).

Nee nee het was eigenlijk de bedoeling om meer te weten te komen over een countdown, dus een timer. En dat is nu al gelukt. Met jou hulp heb ik mijn programma kunnen schrijven.
Maar er komen nog leuke zaken aan bod zoals een timespan.Kan altijd handig zijn voor mensen die iets willen doen met datums en tijd. Dit vooral omdat deze materie nogal complex is.

cptKangaroo

Legacy Member
Een Timer in .NET heeft eigenlijk niks met tijdsbewerking te maken, het is gewoon een manier om op bepaalde intervals een Tick() event te genereren waarbinnen je dan code kan uitvoeren.

Een System.Windows.Forms.Timer synchroniseert met de thread van de Form waarop de Timer staat, en bij een System.Threading.Timer specifieer je zelf de thread waarop de Timer synchroniseert.

Voor jouw programma maakt dit eigenlijk nog niet uit, maar eens je met meerdere Forms begint te werken, zal dat eventueel tot crossthreading errors leiden als je binnen het Tick event van je Forms.Timer iets op een andere Form wilt aanpassen (want iedere Form loopt op een eigen thread). Ik vermeld dit gewoon al even omdat het een makkelijk te maken fout is die niet altijd makkelijk te spotten is, als je niet met threads vertrouwd bent.

Anyway, tijdsbewerking doe je met DateTime, TimeSpan, StopWatch, DateAndTime, Now, ... . Een countdown kan je op vele manieren bouwen, maar in essentie is een countdown gewoon het verschil tussen een eindtijd en de huidige tijd.

Nog een voorbeeldje met Timespans (Form1 met daarop een Button1 en Timer1):

Code:
Public Class Form1

    Public zEndTime As New TimeSpan(Now.AddMinutes(1).Ticks)
    Public zTimeLeft As TimeSpan = zEndTime - New TimeSpan(Now.Ticks)


    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Timer1.Enabled = True
        Timer1.Start()
    End Sub

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

        zEndTime = New TimeSpan(Now.AddMinutes(1).Ticks)
    End Sub

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

        zTimeLeft = New TimeSpan(zEndTime.Ticks - Now.Ticks)
        Dim zCountDownText As String = zTimeLeft.Hours.ToString("00") & ":" & zTimeLeft.Minutes.ToString("00") & ":" & zTimeLeft.Seconds.ToString("00")
        ' in .NET Framework v4 -> Dim zCountDownText As String = zTimeLeft.ToString("hh:mm:ss")

        Me.Text = zCountDownText
    End Sub

End Class
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan