Guida al Visual Basic: L’orologio di Windows
Ho voluto terminare questa guida di base con un esempio forse un pò troppo complesso, che però fa vedere quanto potente possa essere il VB6: la creazione di un orologio analogico e di un calendario perpetuo. L’esempio è stato realizzato unendo alle funzioni data/ora e ai metodi delle picture anche un pò di matematica. Dividiamo la trattazione in due parti:
1) Orologio analogico
2) Calendario perpetuo
Orologio analogico
Per prima cosa aggiungiamo i controlli Picture1, label 1, Timer1 al nuovo progetto, tralasciamo per ora i pulsanti di regolazione dell’ orologio
Cominciamo con il load del form |
Private Sub Form_Load() ‘ valori iniziali per angolatura secondi,minuti,oresecondi = Second(Now()) minuti = Minute(Now()) ore = Hour(Now()) * 5 angolosecondi = 90 – secondi * 6 angolominuti = 90 – minuti * 6 angoloore = 90 – ore * 6 – 30 * minuti / 60End Sub |
Le prime funzioni già le conosciamo; ci restituiscono secondi ,minuti, ore attuali. Le lancette di minuti e secondi hanno però un angolo iniziale; quando sono a zero formano un angolo di 90° con l’asse delle x, ed ogni secondo decrementano di 6° (infatti 360° corrispondono a 60 secondi o minuti). Differente è il discorso per per le ore; se ci pensate un pò su capirete la corrispondenza nella formula descritta. Ora per aggiornare la posizione delle lancette, usiamo l’evento timer che scatta ad ogni secondo: |
Private Sub Timer1_Timer() Label1.Caption = Format(Now(), “hh.mm.ss”)’ qui visualizziamo l’ora nella label If angolosecondi = -270 Then angolosecondi = 90 angolominuti = angolominuti – 6 End If angolosecondi = angolosecondi – 6 ‘ ad ogni secondo l’angolo diminuisce di 6° minuti = Minute(Now()) ore = Hour(Now()) * 5 angoloore = 90 – ore * 6 – 30 * minuti / 60Call disegna(angolosecondi, angolominuti, angoloore) Picture1.Visible = True End Sub |
l’ angolo secondi decrementa di 6° ad ogni secondo; differente è il discorso per i minuti che scattano di 6° ogniqualvolta la lancetta compie un giro completo, cioè parte da 90° e arriva a -270°. Adesso non basta che disegnare le lancette, usando la funzione Call disegna(angolosecondi, angolominuti, angoloore) c he come vedete accetta in ingresso i tre angoli delle tre lancette. Per disegnare le lancette usiamo il metodo line del controllo picture che disegna una retta:Picture1.Line (X1, Y1)-(X2, Y2), coloredove x1,y1 – x2,y2 sono le coordinate dei due punti della retta, nel sistema di coordinate che ha come origine l’angolo superiore sinistro della Picture.
Attenzione: le x vanno da sinistra verso destra, mentre le y vanno dall’alto verso il basso. Disegniamo ora le tre lancette: |
Public Function disegna(gradi, minuti, ore) Picture1.Clsdisegnaorologio ‘ disegna la parte fissa dell’orologio Dim a, b, c, d, e, f As Doublepgreco = 3.14 a = 1200 * Sin(gradi * pgreco / 180) b = 1200 * Cos(gradi * pgreco / 180) Picture1.DrawWidth = 1 Picture1.Line (1250, 1250)-(1250 + b, 1250 – a), vbBlack ‘l ancetta secondi c = 1150 * Sin(angolominuti * pgreco / 180) d = 1150 * Cos(angolominuti * pgreco / 180) Picture1.DrawWidth = 3 Picture1.Line (1250, 1250)-(1250 + d, 1250 – c), &H808000 ‘lancetta minuti e = 850 * Sin(angoloore * pgreco / 180) f = 850 * Cos(angoloore * pgreco / 180) Picture1.DrawWidth = 5 Picture1.Line (1250, 1250)-(1250 + f, 1250 – e), &H808000 ‘ lancetta ore Picture1.DrawWidth = 8 Picture1.PSet (1250, 1250), vbBlack End Function |
Tralasciamo per ora la funzione disegna orologio che disegna le tacche dell’orologio, e soffermiamo la nostra attenzione sul disegno delle lancette |
Usiamo le funzioni sin e cos (seno e coseno) del Vb che però devono avere l’argomento in radianti: per questo usiamo la conversione *pgreco / 180 ; La proprietà DrawWidth ci permette invece di dare dimensione diversa alle lancette dove abbiamo anche specificato colori differenti. Per ultimo la funzione Picture1.PSet ci permette di disegnare un punto per il centro dell’ orologio. Dobbiamo inoltre con il metodo Picture1.Cls cancellare la posizione precedente delle lancette. Analizziamo anche la funzione disegnaorologio: |
Public Sub disegnaorologio() Dim i Dim x As Double Dim y As Double Dim r For i = 1 To 360 Step 6 x = 1250 * Cos(i * pgreco / 180) y = 1250 * Sin(i * pgreco / 180) r = i Mod 5 If r = 1 Then Picture1.DrawWidth = 4 ‘ dimensione del punto Picture1.PSet (1250 + x, 1250 – y), &H808000 ‘ verde chiaro Else Picture1.DrawWidth = 2 ‘ dimensione del punto Picture1.PSet (1250 + x, 1250 – y), vbWhite ‘Bianco End IfNext i End Sub |
Qui usiamo anche la funzione i Mod 5 che mi restituisce 1 ogni 5 minuti per disegnare di verde le tacche dei minuti (è il resto della divisione per 5) |
Regolazione dell ‘oraLa funzione time che restituisce l’ora di sistema, funziona anche all’incontrario, cioè serve anche per l’assegnazione. Per incrementare i secondi usiamo allora un pulsante con il seguente codice: |
Dim s As Integer Dim t t = Time s = Second(Time) Time = Hour(t) & “.” & Minute(t) & “.” & (s + 1) Mod 60 Label1.Caption = Format(Now(), “hh.mm.ss”) secondi = Second(Now())angolosecondi = 90 – secondi * 6 |
Come vedete leggiamo i secondi e li incrementiamo ad ogni click del pulsante, mantenendo costanti ore e minuti. Passiamo inoltre il nuovo angolo per la lancetta. Analogamente procediamo per modificare minuti e ore |
Private Sub Command4_Click() Dim m As Integer Dim t t = Time m = Minute(Time) Time = Hour(t) & “.” & (m + 1) Mod 60 & “.” & Second(Time) Label1.Caption = Format(Now(), “hh.mm.ss”) minuti = Minute(Now())angolominuti = 90 – minuti * 6 End Sub ‘————————————————– Private Sub Command5_Click() Dim h As Integer Dim t t = Time h = Hour(Time) Time = (h + 1) Mod 24 & “.” & Minute(t) & “.” & Second(t) Label1.Caption = Format(Now(), “hh.mm.ss”) secondi = Second(Now())ore = Hour(Now()) * 5 minuti = Minute(Time) angoloore = 90 – ore * 6 – 30 * minuti / 60 End Sub |
2) Calendario perpetuo
Per creare il calendario usiamo un concetto molto interessante, che è quello della matrice di controlli. Ormai sappiamo disegnare una label in ambiente di progettazione, ma come disegnare tutti i quadratini del calendario in esecuzione? E’ infatti impensabile stare lì a disegnare decine e decine di quadratini. Creiamo allora una label di nome label e nella proprietà index scriviamo 0; abbiamo così creato una matrice di label (label(i)) ora le carichiamo all’ avvio del programma, mettendo nel load del form la seguente funzione:
Public Sub caricacalendario() Dim i As IntegerDim r As Integer Dim stpx As Integer stpx = 300 r = 1 Dim IND As Integer For r = 1 To 7For i = 1 To 7 IND = i + (r – 1) * 7 Load Label(IND) With Label(IND) .Left = (i + 1) * stpx + 20 .Top = Label(0).Top * r + 20 .Visible = True Next i Label(1).Caption = “L” For i = 8 To 49 End Sub |
La funzione Load Label(IND) carica nel form la label di indice IND ; ora possiamo modificare proprietà e caption delle label accedendovi semplicemente con dei cicli for sull ‘indice: per esempio nel ciclo for:For i = 1 To 7 Label(i).BackColor = &H808080 Label(i).ForeColor = vbWhite Next i cambiamo il colore dei giorni della settimana facendoli apparire bianchi su sfondo grigio scuro. Una volta caricato il calendario, bisogna disegnarlo inserendo i giorni nel giusto posto della settimana: |
Public Sub disegnacalendario(data_i As Date)Dim g Dim m Dim a Dim data As Date If Month(data_i) < “10” Then m = “0” & Month(Date) Else m = Month(data_i) End If Dim giornoattuale As Integer giornoattuale = Day(data_i) data = “01/” & m & “/” & Year(data_i) Dim t For i = 1 To numerogiorni(data) Label(i + 8 + g – 2).Caption = i End If |
La funzione Weekday(data) restituisce il giorno della settimana (lunedì, martedi, ecc) sotto forma numerica; nella istruzione select vediamo la corrispondenza, e riusciamo a scrivere nella posizione giusta il primo giorno del mese; per sapere quanti giorni ha un mese usiamo la funzione numerogiorni(data): |
Public Function numerogiorni(data) As Integer Dim giorno As Date Dim f As Integer Dim m As Integer m = Month(data) f = 0Do giorno = data + fIf Month(giorno) <> m Then numerogiorni = f Exit Do End If f = f + 1 Loop End Function |
Partendo dal primo giorno del mese incrementiamo il giorno finché non cambia anche il mese; in f troviamo il numero di giorni e la assegniamo alla funzione; Con l’istruzione condizionale::If i = giornoattuale Then Label(i + 8 + g – 2).BackColor = &HC00000 Label(i + 8 + g – 2).ForeColor = vbWhiteassegniamo al giorno attuale ( giornoattuale = Day(data_i) ) il colore Blue |
Consiglio di scaricare l’esempio analogico.zip per approfondire meglio. |