Hallo Leute!
Ich habe mir mit Visual Basic 6 einen Art kleine Stoppuhr gebastelt. Man gibt eine Startzeit ein und sie zählt dann auf null runter, um danach ein ereignis zu starten.
Das blöde daran ist nur, dass sie nur Sekunden zählt. Gibt man also als Startzeit 2 min 10 s ein, dann zählt die Stoppuhr von 130 s an rückwärts. Nun wäre es mir aber lieber, wenn sie im Format 02:10 rückwärts zählen würde. Der mir dafür bekannte Befehal Format(CStr(nSek), "mm:ss") funktioniert da leider aber nicht. Verwendet man ihn, zeigt die Stoppuhr eine völlig falsche Startzeit an und zählt auch nicht mit.
Hier mal ein Auszug aus meinem Quelltext:
Private Sub Command1_Click()
Dim Startzeit As Integer
Timer1.Enabled = True
If Text1.Text = "" And Text2.Text = "" Then
MsgBox ("Keine Startzeit eingegeben!")
GoTo Ende
Else
If Text1.Text = "" Then Text1.Text = 0
If Text2.Text = "" Then Text2.Text = 0
Startzeit = (Text1.Text * 60) + Text2.Text
nSek = Startzeit ' Timer initialisieren
Timer1.Interval = 1000 ' entspricht einer Sekunde
Label1.Caption = CStr(nSek) & " s" ' Countdown
End If
Ende:
End Sub
Private Sub Timer1_Timer()
nSek = nSek - 1 ' und wieder eine Sekunde vorbei
Label1.Caption = CStr(nSek) & " s"
If nSek Timer1.Enabled = False
[...........]
Else
End If
End Sub
Weiterhin such ich noch eine Möglichkeit, wie man am Ende des Timers evtl. einen roten Kreis (Shape) blinken lassen könnte, damit der Nutzer schneller sieht, dass die Zeit um ist.
Ich hoffe, ihr könnt mir mit guten Ideen helfen.
Grüße,
Mic2004.
Programmieren - alles kontrollieren 4.941 Themen, 20.708 Beiträge
mir war das jetzt ein bissl zuviel zum lesen aber hast du schon mal daran gedacht eine startzeit also x= now() oder so zu nehmen und mit DateDiff zu rechnen ?
Da AFAIK die interne darstellung von zeit als kommazahl in tagen erfolgt, ist deine variante mit Format(...) natürlich nicht zielführend. Ersatzweise kannst du mit:
Private Function Sec2MSStr(sec) As String
Sec2MSStr = Right("0" & Mid(Str(sec \ 60), 2), 2) & ":" & Right("0" & Mid(Str(sec Mod 60), 2), 2)
End Function
statt:
Label1.Caption = CStr(nSek) & " s"
einfach:
Label1.Caption = Sec2MSStr(nSek) & " s"
schreiben.
mr.escape
Hallo "mr.escape"!
Danke für deinen Tipp. Genau so sollte es sein. Könntest du mir (als Anfänger) aber mal zu meiner Verständnis kurz erklären, wie diese Funktion funktioniert? Allein wäre ich da nie drauf gekommen.
Und hast du evtl. auch noch so eine einfache und gute Idee, was das Blinken eines (oder zweier) Krieses (Shape) angeht?
Danke und Grüße,
Mic2004.
wie diese Funktion funktioniert?
"\" ist eine ganzzahldivision, d.h. ohne nachkommastellen (hier also die minuten).
"Mod" ist die Modulo_(Rest)-funktion (hier die sekunden nach abzug der vollen minuten).
"Str" erzeugt eine zeichenkette aus der zahl.
"Mid(...,2)" schneidet die erste stelle der zeichenkette ab, weil dort bei positiven zahlen eine leerstelle ist ("-" bei negativen zahlen).
"Right("0" &..., 2)" fügt ggf eine führende "0" an, um auch bei einstelligen zahlen auf die erforderlich länge zu kommen.
das Blinken eines (oder zweier) Krieses (Shape) angeht?
Die sichtbarkeit per timer umschalten:
If Shape1.Visible Then Shape1.Visible = False Else Shape1.Visible = True
mr.escape
Gibt es in VB nichts in der Richtung Shape1.Visible = NOT Shape1.Visible? ;-)
Hallo "mr.escape" und "Borlander"!
Eure beiden Code-Zeilen funktionieren aber beide nicht so, wie ich es haben möchte. Damit kann man den Kreis (Shape1) nur einmal ein oder ausschalen. Legt man den Code also auf einen CommandButton, muss man den immer anklicken, damit der Kreis "an" und wieder "aus" geht.
Private Sub Command5_Click()
Shape1.Visible = Not Shape1.Visible
End Sub
Das nützt mir nichts. Ich möchte, dass der Kreis nach Ablauf der Zeit automatisch blinkt. Ich könnte mir evtl. vorstellen, dass man das über einen zweiten Timer machen müsste. Vielleicht über eine Art Loop, dass der Kreis immer "an" ist, wenn der Timer eine gerade Zahl zählt und immer "aus" ist, wenn der Timer eine ungerade Zahl zählt. Die Sache müsste nur eben von allein immer weiter laufen (und das möglichst ohne den Computer zu blockieren).
Grüße,
Mic2004.
Da hatte ich gar nicht weiter drauf geachtet. Die Boolean-Negation mit IF war mir allerdings ins Auge gesprungen ;-)
Gibt es in VB nicht sowas wie ein Timer-Objekt? In Delphi gibt es dazu in der VCL die Klasse TTimer. Bei deren Instanzen kann man wie bei einem Button eine Ereignisbehandlung definieren die dann in einem festgelegten Intervall aufgerufen wird solange der Timer aktiviert ist. Würde mich wundern wenn es bei VB nicht was ähnliches gäbe...
Gruß
Borlander
Legt man den Code also auf einen CommandButton, muss man den immer anklicken, damit der Kreis "an" und wieder "aus" geht.
Deshalb schrieb ich ja auch Die sichtbarkeit per timer umschalten:
Die umschaltung per "If" kommt daher, weil nicht nur einfache boolsche operationen denkbar sind, sondern auch z.b. farben u.ä.
Dafür reicht dann keine (logische) formel mehr, sondern nur das gute alte "If ... Then ... Else" (sofern man nicht eine boolsche zustandsvariable [mit 0 und 1 als wert und 1-wert als formel bzw. 1 und 2 sowie 3-wert] und passende attribut-felder bemüht).
mr.escape
Hi,
es gäbe auch die Möglichkeit, die Startzeit in Variable zu laden und diese runterzuzählen. Also, die Startzeit sei 3 h, 20 min und 35 sec. Jetzt setzt man die Variablen (alle als Integer) wie folgt:
mInt_Hour = 3
mInt_Min = 20
mInt_Sec = 35
Danach startet man den Timer, der auf Interval 1000 = 1 sec eingestellt ist.
Nach der ersten Sekunde führt der Timer "mInt_Sec = mInt_Sec -1" aus.
Nach weiteren 35 Sekunden ist mInt_Sec = -1. Diesen Wert fragt man per If ab, und wenn dem so ist, wird mInt_Min um 1 reduziert und mInt_Sec wird auf 59 gesetzt. Wenn man das schon bei mInt_Sec = 0 machte, müsste der nächste Startwert für mIntSec 60 sein. Man zeigt ja nicht an, wieviel Zeit verstrichen ist, sondern welche Restzeit verbleibt.
Irgendwann ist mInt_Min = 0 , dann wird es Zeit, mInt_Hour um 1 zu reduzieren und mInt_Min UND mInt_Sec auf 59 zu setzen.
Jede Variable kann man sich per Cstr() anzeigen lassen wo man möchte, z.B. je ein Label für Hour, Min und Sec.
Irgendwann sind alle Variablen auf 0: If mInt_Sec + mInt_Min + mInt_Hour = 0 Then
und an dieser Stelle kann man den Timer entweder stoppen oder weiter laufen lassen und damit den roten Kreis bedienen: Shape1.Visible = Not Shape1.Visible, d.h., der Kreis blinkt im Sekundentakt.
Wie der Timer gestoppt wird, ist letztlich eine Design-Frage des persönlichen Geschmacks. Bei der Gelegenheit setzt man dann Shape1.Visible = False.
Das funktioniert, ich benutze es selber. Hier ein Code-Auszug (zu blöd, dass man Code hier nicht eingerückt darstellen kann):
mInt_seconds = mInt_seconds - 1
If mInt_seconds = -1 Then
mInt_seconds = 59
If mInt_minutes = 0 Then
mInt_minutes = 59
If mInt_hours > 0 Then
mInt_hours = mInt_hours - 1
End If
Else
mInt_minutes = mInt_minutes - 1
End If
End If
If mInt_seconds + mInt_minutes + mInt_hours = 0 Then
Shape1.Visible = Not Shape1.Visible
'oder Me.Timer1.Enabled = False
End If
HAND
Sylvia
zu blöd, dass man Code hier nicht eingerückt darstellen kann
Kann man schon, in dem man führende leerzeichen/tabs (sowie alle mehrfach-leerzeichen) durch die entsprechende anzahl " " ersetzt und das ganze am besten in <tt>...</tt> packt.
z.b.:
If mInt_seconds + mInt_minutes + mInt_hours = 0 Then
Shape1.Visible = Not Shape1.Visible
'oder Me.Timer1.Enabled = False
End If
wird zu:
<tt>If mInt_seconds + mInt_minutes + mInt_hours = 0 Then
Shape1.Visible = Not Shape1.Visible
'oder Me.Timer1.Enabled = False
End If</tt>
Siehe auch: http://www.nickles.de/static_cache/538349582.html
mr.escape
Na dann mal zum Testen:
mInt_seconds = mInt_seconds - 1
If mInt_seconds = -1 Then
mInt_seconds = 59
If mInt_minutes = 0 Then
mInt_minutes = 59
If mInt_hours > 0 Then
mInt_hours = mInt_hours - 1
End If
Else
mInt_minutes = mInt_minutes - 1
End If
End If
If mInt_seconds + mInt_minutes + mInt_hours = 0 Then
Shape1.Visible = Not Shape1.Visible
'oder Me.Timer1.Enabled = False
End If
HAND
Sylvia
Hallo Leute!
Ich habe leider jetzt erst mitbekommen, dass ich euch um mein Problem Gedanken gemacht habt. Die E-Mail-Benachrichtigung hatte mich wohl im Stich gelassen.
Was wäre denn nun die einfachste Lösung meine zwei Kreise (wechselweise) blinken zu lassen?
Grüße,
Mic2004.
Poooh,
und ich dachte schon "wieder ein undankbarer Typ".
Die einfachste Lösung, um zwei - ich hatte gar nicht mitbekommen, dass es sich um mehr als einen Kreis handelt - Kreise abwechselnd blinken zu lassen, ist (in Anlehnung an mein voriges Posting):
If mInt_seconds + mInt_minutes + mInt_hours = 0 Then
Shape1.Visible = Not Shape1.Visible
Shape2.Visible = Not Shape1.Visible
End If
Bevor die Zeit abgelaufen ist, sind beide Kreise nicht zu sehen.
1)
Nach Ablauf der Zeit leuchtet der erste Kreis (Shape1) auf; da der zweite Kreis (Shape2) genau das Gegenteil vom ersten Kreis tun soll, bleibt er zunächst aus.
2)
Beim nächsten Timer-Durchgang ist die Zeit immer noch abgelaufen, aber jetzt soll Shape1 das Gegenteil tun von dem, was er bis dahin gemacht hat: er wird unsichtbar; und da Shape2 immer das Gegenteil von Shape1 macht, leuchtet jetzt der zweite Kreis auf.
Beim nächsten Timer-Durchgang wird wieder 1) gesetzt, etc.
Falls der Blinkrythmus zu langsam ist, kannst du ja gleich nach der If-Zeile einfügen "Me.Timer1.Interval = 500" oder welcher Wert dir zusagt; musst einfach ausprobieren.
Einfacher geht's nicht, es sei denn, du hattest etwas Komplizierteres im Sinn, wann und in welchem Abstand welcher Kreis blinken soll; dann musst du das noch mal genauer erläutern.
HAND
Sylvia
Hallo!
Da bin ich wieder. Wo genau müsste ich denn diesen Quelltext einfügen, dass er funktioniert. Nachdem mein "Countdown" auf 00:00 ist, stoppt ja mein Timer1 auch eigentlich.
Jedenfalls wenn ich deinen Quelltext ans Ende meines Private Sub Timer1_Timer() setze, kommt immer die Fehlermeldung "Variable nicht definiert."
Grüße,
Mic2004.
Hi,
also, auf welche Variable sich die Fehlermeldung "Variable nicht definiert" bezieht, weisz ich natürlich nicht. Deshalb mal ganz allgemein:
Eigentlich müsste klar sein, dass Variablen auf Modulebene deklariert werden müssen, wenn man deren Werte procedure-übergreifend am Leben erhalten will. Und da die Anfangswerte der von mir verwendeten Variablen nicht im Timer gesetzt werden, geschieht das logischerweise in einer anderen Prozedur, wozu aber die Variablen eben auf Modulebene deklariert werden müssen, sonst funktioniert es nicht.
Alle von mir genannten Variablen, die mit "mInt_" beginnen, werden auf der Form ganz oben, also auf Modulebene deklariert, deshalb beginnen sie auch mit "mInt_" - m für Modulebene und Int für Typ Integer:
Private mInt_seconds As Integer
Private mInt_minutes As Integer
Private mInt_hours As Integer
Die Werte für die Variablen setzt du dort, wo der Benutzer die Anfangswerte setzt. Wenn das eine Textbox ist, wäre das z.B. der Change-Event:
Private Sub TextHours_Change()
mInt_hours = 0 'Auf einen Wert voreinstellen, falls die folgenden Bedingungen nicht zutreffen
With Me.TextHours
If .Text "" Then
If IsNumeric(.Text) = True Then
mInt_hours = CInt(.Text)
End If
End If
End With
End Sub
Das gleiche dann für die Textboxen für Minuten und Sekunden anlegen.
Irgendwo kannst du noch einen Check einbauen, dass z.B. Minuten und Sekunden keinen Wert über 59 haben.
Alternativ kannst du die Übergabe der Textbox-Inhalte nach dem selben Schema (exakt derselbe Code) mit dem Button verbinden, der den Timer startet, dann brauchst du zumindest hierfür den Change-Event nicht. Der Change-Event ist aber hilfreich um festzustellen, dass der User gültige Angaben gemacht hat, und davon abhängig kann man den Start-Button aktivieren/deaktivieren. Dann allerdings würde ich den Überprüfungscode in eine extra Sub auslagern und die Sub von den Change-Events aufrufen:
Private Sub StartEnable()
'Start-Button deaktivieren
'Prüfung für Stunden (siehe Code oben)
'Prüfung für Minuten (Code analog zu Stunden)
'Prüfung für Sekunden (Code analog zu Stunden)
'Start-Button aktivieren, falls alle drei Prüfungen erfolgreich sind.
End Sub
Wenn nach dem Countdown Timer1 stoppt, musst du einen zweiten Timer nehmen, um die Kreise blinken zu lassen. Diesen zweiten Timer kannst du z.B. nach Ablauf der Zeit durch den ersten Timer starten und diesen zweiten Timer dann irgendwo wieder ausschalten. Für die von mir genannten Objekte Shape1 und Shape2 musst du dann natürlich die Namen für deine Kreise einsetzen.
Nun weisz ich ja nicht, was sonst noch alles in deinem Timer1 passiert, aber das kann man ja abschalten, wenn die Zeit abgelaufen ist und der Timer weiterhin aktiv bleiben soll, damit die Kreise blinken. Du schreibst dann einfach: "If mInt_seconds + mInt_minutes + mInt_hours > 0 Then" heiszt: solange die Zeit noch nicht abgelaufen ist, mache dies und das, auch z.B., dass die Kreise Visible = False sind - End If. Und danach eben: "If mInt_seconds + mInt_minutes + mInt_hours = 0 Then" - heiszt: Erst wenn die Zeit abgelaufen ist, dann lasse die Kreise blinken - End If. Und irgendwo auszerhalb des Timers eine Abschaltmöglichkeit desselben vorsehen.
Ich schalte jetzt auch ab.
HAND
Sylvia
Hallo genau einen solchen Code suche ich wollte fragen ob du den noch Original hast und ihn mir vielleicht schicken kannst.
MFG
Djschlod