VB.NET Timer Countdown

VB.NET Timer Countdown
VB.NET Timer Countdown

VB.NET Timer Countdown

Du fragst Dich, wie Du in VB.NET einen Timer Countdown erstellen kannst? Lerne in diesem Beitrag wie!

Falls Du noch gar nichts über das Timer-Control weißt, empfehle ich Dir, meinen allgemeinen Beitrag über das VB.NET Timer Steuerlement anzusehen.

Ergänzend dazu habe ich auch noch einen weiteren Beitrag über die dynamische Erstellung eines Timers zur Laufzeit geschrieben.

Vorschau – VB.NET Timer Countdown

Hier drunter siehst Du, wie die Umsetzung eines Countdowns zum Beispiel aussehen könnte.

VB.NET Timer Countdown gif
VB.NET Timer Countdown gif

Das erste Beispiel – auf einer Form mit Label

Ich denke als erstes und beliebtestes Beispiel, kommt einem die Umsetzung auf einer Form in den Sinn.

Daher machen wir es uns einfach und beginnen direkt damit 😊!

Alles was Du dafür letztendlich brauchst, hast du mit wenigen Handgriffen zusammengeklickt!

Benötigte Steuerelemente

Form

Wir haben uns hierbei entschieden, den Countdown auf einer Form darzustellen, daher brauchen wir natürlich eine Form.

Timer

Für dieses Beispiel brauchen wir selbstverständlich einen Timer, wer hätte das gedacht.. Zack, rauf auf die Form, oder im Code der Klasse als WithEvents Variable/Eigenschaft deklariert – wie Du möchtest.

Hier habe ich den Timer übrigens tmrCountdown genannt, Du solltest natürlich auch einen vernünftigeren Namen als „Timer1“ wählen 😉!

Label

Zu guter Letzt hatten wir geplant, den Countdown selbst – also die Zahlen in einem Label darzustellen. Ziehe daher ein Label auf die Form.

Auch dem Label wurde ein aussagekräftigerer Name als „Label1“ verpasst. Hier habe ich das Label lblNumbergenannt.

Styling der Komponenten

Im folgenden Schritt kümmern wir uns ein wenig um das Styling der Controls, auch wenn wir hier natürlich keine Spiel-like-Grafik haben werden, kann es ja zumindest ein wenig „schöner“ werden.

Die Form stylen

Um das Ganze ein wenig sichtbarer zu gestalten, nehmen wir uns zuerst die Eigenschaften der Form vor.

Ich würde vorschlagen, die Eigenschaft StartPosition“ der Form auf „CenterScreen“ zu stellen.

Wie der Name schon sagt, wird die Form so standardmäßig zentriert auf dem Bildschirm angezeigt.

Die Hintergrundfarbe der Form, also die „BackColor“ habe ich auf Black“ gestellt. So haben wir einen guten Kontrast, Welcher irgendwie an ein Kino erinnert.

Für die Größe der Form habe ich 189×253 gewählt, ist natürlich auch Dir überlassen!

Die Anzeige in einem Label

Wir verpassen dem Label eine ausreichende Größe, also so ungefähr eine Font-Größe von 120.

Anschließend habe ich mich für die Schriftart Consolas entschieden, Welche übrigens die Standard-Schrift von Visual Studio ist.

Zuletzt bekommt das Label die Schriftfarbe „White“, um den oben angesprochenen Kontrast zu bekommen.

Der Code

Im nächsten Abschnitt kommen wir zu dem Code, den wir benötigen um das VB.NET Timer Countdown Beispiel zum Laufen zu bekommen.

Das Timer Tick-Ereignis

Zuerst nehmen wir das Tick-Ereignis des Timersklicke z. B. doppelt auf den Timer, oder wähle das Ereignis über Designer und Co. aus:

Private Sub tmrCountdown_Tick(sender As Object, e As EventArgs) Handles tmrCountdown.Tick
    Dim currentNumber = Convert.ToInt32(lblNumber.Text)
    Dim countDownFinished = currentNumber = 0
    If countDownFinished Then
        tmrCountdown.Stop()
        MessageBox.Show("Countdown finished")
        Return
    End If
    currentNumber -= 1
    lblNumber.Text = currentNumber.ToString()
End Sub

FormClosing-Ereignis – sauber schließen

Um die Form sauber zu schließen, sprich die Arbeit vorher korrekt zu beenden, fügen wir folgenden Ereignishandler hinzu.

Dieser sorgt dafür, dass der Timer beim Schließen der Form gestoppt wird.

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        tmrCountdown.Stop()
    End Sub

Auch wenn der Timer vermutlich durch die Assoziation zur Form (wenn man Ihn per Drag & Drop auf die Form zieht) automatisch disposed wird, ist ein Gedanke daran nicht verkehrt.

Denn auch in Zukunft sollte man solche Sachen nach Möglichkeit bedenken, um z. B. potentielle Memory-Leaks, etc. zu vermeiden.

Den Countdown starten

Ich habe mich dazu entschieden, den Timer durch einen Klick auf das Label starten zu lassen.

Auch hierzu kann man einen Doppelklick auf das Label machen, oder über den Designer arbeiten.

Private Sub lblNumber_Click(sender As Object, e As EventArgs) Handles lblNumber.Click
    tmrCountdown.Start()
End Sub

Wenn man möchte, dass der Timer beim Start des Programms sofort loslegt, kann statt dem vorherigen Code natürlich auch die Enabled-Eigenschaft des Timers bereits im Designer auf True stellen.

VB.NET Timer Countdown die Zweite – auf einer Form mit GDI+

Im zweiten zwar etwas schwierigeren, jedoch interessanteren Beispiel, schauen wir uns das Zeichnen des Countdowns mit GDI+ an.

Dies wäre zum Beispiel nützlich, wenn Du vorhast ein eigenes kleines Spiel mit VB.NET zu entwickeln.

Hier kümmern wir uns nun selbst um das Zeichnen des Countdowns, statt Ihn durch ein Label darzustellen.

Benötigte Steuerelemente

Statt wie bei den Steuerelementen des ersten Beispiels ein Label zu verwenden, verzichten wir hier darauf. Wir übernehmen die Darstellung des Countdowns mit GDI+ und zeichnen selbst.

Styling der Komponenten

Hier verfahren wir ähnlich wie oben, daher ist es kein großer Mehraufwand.

Der Code

3 Eigenschaften kommen in der Form hinzu

Public Property CurrentNumber As Integer
Public Property CountdownFont As Font
Public Property CountdownBrush As Brush

Mir ist an dieser Stelle wichtig, die Eigenschaften im Konstruktor nur ein einziges Mal zuzuweisen und anschließend nur noch abrufen zu müssen.

Bei vielerlei Code der so im Netz tummelt, stellt man fest, dass vor Allem Anfänger, „faulere Leute“ und die „Copy & Paster“ in jedem Durchlauf z. B. die Instanz des Fonts, usw. immer wieder neu erstellen – ein Graus..

Ein ressourceneffizientes arbeiten ist für mich persönlich sehr wichtig, auch wenn man freilich nicht immer an alles denken kann..

CurrentNumber

Die CurrentNumber stellt wie der Name schon sagt unsere aktuelle Countdown-Zahl dar.

Da wir in diesem Beispiel ja nicht mehr den Inhalt des Labels als Zwischenspeicher der Zahl missbrauchen können, ist dies eine der richtigen Alternativen.

Zum einen erleichtert die klassenweite Deklaration den Zugriff aus verschiedenen Methoden und zum anderen fühlt sich die Assoziation zur Form hier richtig an.

CountdownFont

Mit dieser Eigenschaft bestimmen wir den Font des Countdowns.

Hier gilt es zu beachten, dass ein Font nicht schlichtweg nur den Namen des Fonts, sondern auch Styling-Informationen wie Größe und Stärke/Dicke enthält.

Wie im vorherigen Beispiel habe ich die Schriftart bei Consolas und die Größe bei 120 belassen.

Hier habe ich auch wie oben den „FontStyle“ auf dick, also auf „Bold“ gesetzt.

CountdownBrush

Der Brush ist sozusagen die Farbe die wir für den selbst gezeichneten Countdown verwenden.

Wir verwenden auch hier die Farbe „White“, indem wir auf Brushes.White zugreifen.

Konstruktor

Sub New()
    InitializeComponent()
    DoubleBuffered = True
    CurrentNumber = 5
    CountdownFont = New Font("Consolas", 120, FontStyle.Bold)
    CountdownBrush = Brushes.White
End Sub

Im Konstruktor weisen wir einmalig alles zu, was wir für unsere Arbeit brauchen.

Natürlich ist die CurrentNumber hier eine Ausnahme, da diese sich ja durch den Countdown verändern wird.

Neu könnte für Dich hier ggf. die Eigenschaft namens DoubleBuffered sein.

An dieser Stelle reicht denke ich die Erklärung, dass die Eigenschaft das eventuelle Flackern der Form beim Zeichnen ein wenig besser in den Griff bekommt.

Das Zeichnen des Countdowns mit GDI+

„Das Beste kommt zum Schluss„, heißt es doch immer so schön!

Nun kommen wir zum Code, der für das Zeichnen des Countdowns verantwortlich ist.

Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    Dim numberString = CurrentNumber.ToString()
    Dim numberStringSize = e.Graphics.MeasureString(numberString, CountdownFont)
    Dim centerX = (ClientRectangle.Width / 2) - (numberStringSize.Width / 2)
    Dim centerY = (ClientRectangle.Height / 2) - (numberStringSize.Height / 2)
    Dim centerOfForm = New Point(centerX, centerY)
    e.Graphics.DrawString(numberString, CountdownFont, CountdownBrush, centerOfForm)
End Sub

Statt hier „Schlampi-Pampi“ mit der Nummer – also dem Integer – zu hantieren, wandeln wir Diese natürlich vor Gebrauch in einen String namens „numberString“ um.

Danach können wir durch das Graphics-Objekt, Welches uns durch die PaintEventArgs bereitgestellt wird, die Größe des resultierenden Strings messen.

Im darauffolgenden Schritt bestimmen wir jeweils die horizontale und die vertikale Mitte der Form und erstellen eine neue Instanz des Point-Datentyps – praktisch unsere 2D-Koordinaten.

Final können wir die Zahl auf die Form bringen, indem wir die „DrawString„-Methode des e.Graphics Objekts aufrufen.

Diese möchte natürlich alle vorher bestimmten Daten wie den zu zeichnenden String, den Font, einen Brush und letztendlich die Koordinaten wo das Ganze landen soll haben.

Der erste Startversuch

Wenn Du nun einmal F5 drückst, oder das Programm via Visual Studios „Play Knopfins Debugging schickst, siehst Du unsere Zahl „5“.

Leider geht es aber nicht weiter.. Warum? Naja der Timer, Welcher unsere Zahl runterzählt fehlt 😉.

Auch haben wir aktuell das Problem, dass die Zahl verschwindet, wenn Du die Größe der Form beim Debugging veränderst – probiere es ruhig mal aus!

VB.NET Timer Countdown verschwindet GDI
VB.NET Timer Countdown verschwindet GDI

Die verlorene Zahl

Unsere Zahl verschwindet einem aus einem besonders für Anfänger nicht direkt ersichtlichen Grund.

Aktuell zeichnen wir die Zahl nur dann (neu), wenn die Form ihr Paint-Ereignis ausgibt.

Am Anfang ist die Zahl klar sichtbar, weil die Form dieses Ereignis ein Mal bei Start der Anwendung ausgibt.

Um das zu prüfen, könntest Du ja zum Beispiel eine kleine Ausgabe, oder einen Debug-Schritt hinzufügen:

Debug.WriteLine("PAINT")

Invalidate zur Rettung

Wir müssen nun also irgendwie dafür sorgen, dass die Form ihr Paint-Ereignis öfter ausgibt und somit das Zeichnen der Zahl anweisen.

Man könnte jetzt natürlich mit der Brechstange kommen und sowas wie eine Game Loop hinzufügen.

Anderweitig, jedoch genauso heavy könnte man auch einen Timer verwenden und der Form im geringen Intervall sagen: „Hey, zeichne dich neu!“.

Um der Form mitzuteilen, dass Sie sich, oder zumindest gewisse Bereiche neu zeichnen – also invalidieren – soll, können wir mit der Methode Invalidate“ erreichen.

Wenn nicht jetzt, wann dann – löl?

Auch hier bitte ich wieder um den Schritt zurück, um zu überlegen: „Wann genau brauche ich denn eine Aktualisierung der Zeichnung“.

Oben im Gif-Bild konnten wir erkennen, dass es offensichtlich nach einer Größenveränderung der Form von Nöten wäre.

Somit hätten wir auch direkt die Maximierung der Form mit abgearbeitet, denn auch da verändert Sie ihre Größe.

Fügen wir also folgenden „Resize“-Ereignishandler hinzu:

Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    Invalidate()
End Sub

Schon ist unser Problem behoben:

VB.NET Timer Countdown GDI bleibt
VB.NET Timer Countdown GDI bleibt

Der Countdown

Zu guter Letzt kommen wir zum Timer selbst, Welcher dafür verantwortlich ist, die Zahl herunterzuzählen.

Den Startschuss geben wir auch hier mit einem Klick-Ereignis, nur dieses mal das Ereignis der Form:

Private Sub Form1_Click(sender As Object, e As EventArgs) Handles Me.Click
    tmrCountdown.Start()
End Sub

Nun noch die paar Zeilen des Timer Tick-Ereignisses – nur dieses Mal ohne Label-Codehinzufügen:

Private Sub tmrCountdown_Tick(sender As Object, e As EventArgs) Handles tmrCountdown.Tick
    Dim countDownFinished = CurrentNumber = 0
    If countDownFinished Then
        tmrCountdown.Stop()
        MessageBox.Show("Countdown finished")
        Return
    End If
    CurrentNumber -= 1
    Invalidate()
End Sub

Hier daran denken, dass auch nach der Änderung der „CurrentNumber“ ein „Invalidate“ passieren sollte, damit unsere gezeichnete Zahl aktualisiert wird.

Fertig 😄!

Downloads

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert