In questo semplice tutorial spiego come creare un orologio da desktop personalizzato. L'idea è nata quando ho visto questo tipo di gadget sul computer di un mio amico. Mi piaceva la possibilità di avere un bell'orologio di grosse dimensioni sullo schermo, in modo da potere sapere senza problemi quale fosse l'ora, e sopratutto di poterlo disegnare come preferivo.
Per questo piccolo programma, ho disegnato con un'applicazione grafica, il quadrante di un orologio rotondo (200x200 pixel), completo di tutti i particolari ad eccezione delle lancette che inserirò nel codice.
Questa è l'immagine salvata in formato PNG:
Orologio_Rosso.png
L'idea di base è piuttosto semplice: in una PictureBox si inserisce l'immagine del nostro orologio e poi su di esso si disegnano le lancette, la cui posizione viene aggiornata secondo per secondo, utilizzando un algoritmo che usa la classe Timer per recuperare i valori di ore, minuti e secondi dall'orologio di sistema.
Avviamo un nuovo progetto Windows Form, e chiamiamolo "Orologio". In Esplora Soluzioni clicchiamo 2 volte su "My Project", selezioniamo il Tab "Risorse" e clicchiamo sulla freccetta nera alla destra del button "Aggiungi Risorsa", quindi scegliamo l'opzione "Aggiungi file esistente" e, nella schermata che appare, selezioniamo il nostro file immagine che rappresenta il quadrante dell'orologio.
Inseriamo, nella form, una PictureBox e un Timer e impostiamo le seguenti prorpietà :
Form1:
FormBorderStyle=None
Size=200;200
Text=Orologio
PictureBox:
Name:PBClock
BackgroundImage=Orologio.My.Resources.Orologio_Rosso
Dock=Fill
Il codice che segue può essere copiato e incollato nell'ordine in cui appare quà perché l'applicazione funzioni correttamente.
Public Class Form1 'coordinate dei punti che individuano le lancette Dim puntoSecondi1 As Point Dim puntoSecondi2 As Point Dim puntoMinuti1 As Point Dim puntoMinuti2 As Point Dim puntoOre1 As Point Dim puntoOre2 As Point 'coordinate della form Dim posX As Integer Dim posY As Integer Dim penna As New Pen(Color.Black, 3) 'incremento necessario per spostare la lancetta delle ore di 6° ogni 12 minuti 'praticamente la lancetta delle ore deve percorrere lo spazio di 5 minuti in un'ora Dim inc As Integer = 0
Tutte e tre le lancette verranno ridisegnate secondo per secondo.
Quella dei secondi vedrà cambiare la sua posizione ogni singola volta, mentre quella dei minuti si modificherà 1 volta ogni 60 secondi.
Discorso a parte va fatto per la lancetta delle ore che deve spostarsi sul quadrante non 1 volta all'ora, bensì in questo lasso di tempo, deve percorrere esattamente lo spazio di 5 minuti. Infatti in ogni orologio analogico l'indicatore delle ore si muove molto lentamente e, per fare un esempio, alle 08:05 sta in una posizione diversa rispetto alle 08:50, più vicina al numero 8 nel primo caso, più prossima al numero 9 nel secondo. Praticamente la lancetta delle ore deve coprire l'ampiezza di 6° ogni 12 minuti. La variabile inc serve a questo scopo.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim finalShape As Region Dim shapePath As Drawing2D.GraphicsPath 'intervallo di 1 secondo Timer1.Interval = 1000 Timer1.Enabled = True 'i terminali delle lancette saranno triangolari penna.EndCap = Drawing2D.LineCap.Triangle 'il form assumerà una forma circolare come il qudrante dell'orologio: (ellipse(0,0,199,199) shapePath = New Drawing2D.GraphicsPath() shapePath.AddEllipse(0, 0, 199, 199) finalShape = New Region(shapePath) Me.Region = finalShape shapePath.Dispose() 'calcola le coordinate dei punti in cui si trovano le lancette quando viene visualizzata la form puntoSecondi1 = CalcolaPunto(6 * DateTime.Now.Second - 90, 70) puntoSecondi2 = CalcolaPunto(6 * DateTime.Now.Second - 90, 6) puntoMinuti1 = CalcolaPunto(6 * DateTime.Now.Minute - 90, 60) puntoMinuti2 = CalcolaPunto(6 * DateTime.Now.Minute - 90, 6) inc = DateTime.Now.Minute \ 12 puntoOre1 = CalcolaPunto(30 * DateTime.Now.Hour - 90 + inc * 6, 40) puntoOre2 = CalcolaPunto(30 * DateTime.Now.Hour - 90 + inc * 6, 6) End Sub 'aggiorna le coordinate dei punti secondo per secondo Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick 'calcola le coordinate dei punti in cui si trovano le lancette al trascorrere dei secondi puntoSecondi1 = CalcolaPunto(6 * DateTime.Now.Second - 90, 70) puntoSecondi2 = CalcolaPunto(6 * DateTime.Now.Second - 90, 6) puntoMinuti1 = CalcolaPunto(6 * DateTime.Now.Minute - 90, 60) puntoMinuti2 = CalcolaPunto(6 * DateTime.Now.Minute - 90, 6) inc = DateTime.Now.Minute \ 12 puntoOre1 = CalcolaPunto(30 * DateTime.Now.Hour - 90 + inc * 6, 40) puntoOre2 = CalcolaPunto(30 * DateTime.Now.Hour - 90 + inc * 6, 6) PBClock.Refresh() End Sub 'Funzione che converte in radianti l'angolo descritto da ogni lancetta e determina le coordinate dei punti 'che le rappresentano. Private Function CalcolaPunto(ByVal angolo As Single, ByVal raggio As Integer) As Point Dim punto As Point 'converte in radianti angolo = CType(angolo * Math.PI / 180, Single) '(100,100) coordinate del centro del quadrante) punto.X = CType(raggio * Math.Cos(angolo) + 100, Integer) punto.Y = CType(raggio * Math.Sin(angolo) + 100, Integer) Return punto End Function Private Sub PBClock_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _ PBClock.DoubleClick Me.Close() End Sub Private Sub PBClock_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles PBClock.Paint Dim g As Graphics = e.Graphics 'lancetta dei secondi g.DrawLine(Pens.Black, puntoSecondi2.X, puntoSecondi2.Y, puntoSecondi1.X, puntoSecondi1.Y) 'lancetta dei minuti g.DrawLine(penna, puntoMinuti2.X, puntoMinuti2.Y, puntoMinuti1.X, puntoMinuti1.Y) 'lancetta delle ore g.DrawLine(penna, puntoOre2.X, puntoOre2.Y, puntoOre1.X, puntoOre1.Y) End Sub
'Sub necessaria per trascinare l'orologio lungo lo schermo con il mouse. A condizioni normali il mouse cattura la posizione dell'angolo in alto a sinistra del controllo, pertanto quando lo si trascina, anche se lo puntiamo al centro della form, il puntatore verrebbe automaticamente spostato nell'angolo Alto-Sx
Private Sub PBClock_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles PBClock.MouseMove
If e.Button = MouseButtons.Left Then
Dim mousePos As Point = Control.MousePosition
mousePos.Offset(posX, posY)
CType(sender, PictureBox).FindForm().Location = mousePos
End If
End Sub
'Cattura la posizione del mouse sulla form e la mantiene lungo tutto il trascinamento
Private Sub PBClock_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles PBClock.MouseDown
posX = -e.X
posY = -e.Y
End Sub
End Class
Immagine dell'orologio finito