Appunti di Programmazione

Creative Commons License

Creiamo un Orologio in VB .Net

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:

Immagine Orologio

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

        				

Oroglogio finito

Immagine dell'orologio finito

Download sorgente "Orologio.zip" ( 241KB )