Scusate il titolo troppo generico, ma non sono riuscito a riassumere la questione in poche parole.
Sto aggiungendo ad un programma una parte di codice che, attraverso un dialog, mostra vari conti alla rovescia consecutivi (in minuti/secondi/decimi), al termine di ognuno dei quali esegue un'operazione.
Il Dialog ha come elementi:
- Un timer (TimerScan)
- Una label che mostra il conto alla rovescia (LabelTime)
- Un tasto per mettere la pausa (non c'è nel codice di esempio)
- Un tasto di uscita (non c'è nel codice di esempio)
Il Problema:
Una volta avviato il timer, il programma dovrebbe dovrebbe eseguire i conti alla rovescia (due nel codice di esempio) e mostrare i tre msgbox, uno ogni volta che entra in una nuova fase.
La fase iniziale è 0, ma essendo le variabili del tempo inizializzate a 0, TimeValue sarà subito = 0 e si entrerà immediatamente nella fase 1, che darà inizio al primo conto alla rovescia per la fase due, e così via.
Quel che accade invece è un continuo apparire dei MsgBox della fase 1.
In pratica il programma entra continualmente nell'if della Sub TimerScan_Timer, esegue il MsgBox, ma NON incrementa la fase.
E questo anche se elimino il Select-Case e metto un solo MsgBox dentro l'if.
Una cosa che ho notato è che, nei primi ingressi dentro l'if, il timer mostra 0:00:-1, che non dovrebbe essere possibile.
In pratica, se tolgo il MsgBox (o qualsiasi operazione complessa al suo posto), il timer pare funzionare correttamente.
Altro strano problema è che, dopo l'unload del Dialog, continua a far apparire i MsgBox (che nell'esempio simulano le operazioni relative alle varie fasi).
PS: cerchiamo di non discutere sul fatto che un altro metodo di implementazione del counter sarebbe stato migliore o peggiore, ma sul perchè questo non funziona!!
Scrivo qui un codice riassuntivo.
codice:
Option Explicit
Const NUM_PHASES As Integer = 3 '// numero di fasi implementate:
'// 1 -> attesa1; 2-> attesa2; 3 -> uscita
Dim timeValue As Integer '// Per determinare quando il conteggio arriva a zero
Dim phase As Integer '// Tiene memoria della fase in atto
Dim decs As Integer
Dim secs As Integer
Dim mins As Integer
Dim waits(NUM_PHASES) As Integer '// Ritardo tra una fase e l'altra, ossia valore di inizio
'// per il conto alla rovescia. Qui per semplicità si possono
'// impostare solo i secondi, da 0 a 59
'// Inizilalizzazioni
Private Sub Form_Activate
waits(0) = 0
waits(1) = 3
waits(2) = 4
waits(3) = 0
phase = 0
decs = secs = mins = 0
End Sub
'// Valuta e decrementa il tempo, gestisce le fasi, avvia le operazioni relative alle fasi.
Private Sub TimerScan_Timer()
'// Aggiorno la label di visualizzazione del tempo
LabelTime.Caption = FormatTime()
'// Calcolo per la valutazione del tempo (se = 0 il conto alla rovescia è terminato)
timeValue = decs + secs + mins
If timeValue = 0 Then '// Se il conto alla rovescia è terminato
'// Modifico la fase
phase = phase + 1
'// Assegno il nuovo conto alla rovescia
'// (Semplificato: imposto solo i sencondi)
secs = waits(phase)
'// Eseguo le operazioni (Qui semplificate con un MsgBox)
Select Case phase
Case 1
Msgbox "Fase 1"
Case 2
Msgbox "Fase 2"
Case Else '// Chiude il Dialog
Msgbox "Fase 3"
Unload Me
End Select
End If
'// Decremento il tempo
NextTime
End Sub
'// Decrementa decs e modifica di conseguenza i valori di secs e mins
Private Sub NextTime()
decs = decs - 1
If decs < 0 Then
decs = 9
secs = secs - 1
If secs < 0 Then
secs = 59
mins = mins - 1
End If
End If
End Sub
'// Formatta la stringa tempo
Private Function FormatTime() As String
FormatTime = mins & ":" & Format(secs, "00") & ":" & decs
End Function