⏱️ Timer e ProgressBar in Windows Forms

Crea applicazioni dinamiche che si aggiornano nel tempo!

🎯 Cosa Imparerai in Questa Lezione

Fino ad ora le tue app facevano qualcosa solo quando l’utente cliccava un pulsante.
Oggi scoprirai come creare applicazioni che si muovono da sole:
orologi che tic-taccano, cronometri che contano, barre di caricamento che si riempiono! ⏰🚀

✨ I Nuovi Controlli Dinamici

⏱️ Timer

Esegue codice automaticamente ogni tot millisecondi!
Perfetto per orologi, countdown, animazioni, controlli periodici.

Es: Ogni 1000ms (1 secondo) aggiorna l’ora corrente

📊 ProgressBar

Barra di progresso che si riempie! Mostra all’utente quanto manca
al completamento di un’operazione.

Es: Download file 0% ▱▱▱▱▱ → 100% ▰▰▰▰▰

🔔 NotifyIcon

Icona nella system tray (in basso a destra vicino all’orologio).
Per app che girano in background e notifiche.

Es: Promemoria che compare ogni 30 minuti

📚 Prerequisiti

Prima di iniziare, dovresti aver completato:

  • ✅ TabControl e DataGridView (Lezione 8)
  • ✅ Gestione eventi
  • ✅ Variabili e operazioni matematiche base

⏱️ Cos’è il Timer?

🤔 Analogia della Vita Reale

Hai presente la sveglia che suona ogni mattina alla stessa ora?
O il metronomo dei musicisti che fa “tic-tac” a ritmo costante?
Il Timer è esattamente questo: un componente che “suona” (esegue codice)
ogni tot tempo!

💡 Come Funziona il Timer

1️⃣ Imposti l’intervallo (es: 1000 millisecondi = 1 secondo)

2️⃣ Scrivi cosa deve fare nel metodo Timer_Tick

3️⃣ Avvii il Timer con timer.Start()

4️⃣ Il codice si ripete automaticamente ogni intervallo!

⚙️ Proprietà Principali:

  • Interval: Tempo in millisecondi (1000 = 1 secondo)
  • Enabled: true = attivo, false = fermo

🎮 Metodi Principali:

  • Start(): Avvia il timer
  • Stop(): Ferma il timer

⚠️ IMPORTANTE: Millisecondi!

Il Timer conta in millisecondi (ms), non secondi!
• 1000 ms = 1 secondo
• 500 ms = 0.5 secondi (mezzo secondo)
• 60000 ms = 60 secondi = 1 minuto
• 100 ms = 0.1 secondi (velocissimo!)

🕐 Esercizio 1: Orologio Digitale

▶ Obiettivo

Crea un orologio digitale che mostra l’ora corrente e si
aggiorna automaticamente ogni secondo! Come quello del computer ma nel TUO programma! 🕐

1

Crea l’Interfaccia

🎨 Controlli Necessari:

  • Label: lbl_ora
    • Text = “00:00:00”
    • Font = Molto grande (es: Arial, 48pt, Bold)
    • ForeColor = Colore che ti piace
    • TextAlign = MiddleCenter
  • Label: lbl_data
    • Text = “01/01/2025”
    • Font = Medio (es: Arial, 16pt)
    • TextAlign = MiddleCenter
  • Timer: timer_orologio
    • Interval = 1000 (1 secondo)
    • Enabled = true (si avvia automaticamente)
💡 Come Aggiungere il Timer:

  1. Nella Toolbox cerca “Timer”
  2. Trascinalo sul form
  3. Appare in basso (non è visibile all’utente!)
  4. Imposta Properties → Interval = 1000
  5. Properties → Enabled = true

2

Il Codice

OrologioDigitale.cs
using System;
using System.Windows.Forms;

namespace OrologioDigitale
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
            // Imposta ora e data all'avvio
            AggiornaOrario();
        }

        // ═══════════════════════════════════════════
        // EVENTO TIMER: Si esegue ogni 1 secondo!
        // ═══════════════════════════════════════════
        private void timer_orologio_Tick(object sender, EventArgs e)
        {
            // Aggiorna l'orario
            AggiornaOrario();
        }

        // ═══════════════════════════════════════════
        // METODO: Aggiorna ora e data
        // ═══════════════════════════════════════════
        private void AggiornaOrario()
        {
            // Ottieni l'ora corrente
            DateTime adesso = DateTime.Now;
            
            // Formatta l'ora come HH:mm:ss (24 ore)
            lbl_ora.Text = adesso.ToString("HH:mm:ss");
            
            // Formatta la data come dd/MM/yyyy
            lbl_data.Text = adesso.ToString("dddd, dd MMMM yyyy");
            
            // BONUS: Cambia colore in base all'ora
            int ora = adesso.Hour;
            
            if (ora >= 6 && ora < 12)
            {
                // Mattino: Arancione
                lbl_ora.ForeColor = Color.Orange;
            }
            else if (ora >= 12 && ora < 18)
            {
                // Pomeriggio: Blu
                lbl_ora.ForeColor = Color.Blue;
            }
            else
            {
                // Sera/Notte: Viola
                lbl_ora.ForeColor = Color.Purple;
            }
        }
    }
}

🎬 Cosa Succede:

  1. L'app si apre e mostra subito l'ora corrente
  2. Ogni 1 secondo il timer_orologio_Tick viene chiamato automaticamente
  3. Il metodo AggiornaOrario() prende l'ora attuale e la mostra
  4. Il colore cambia in base all'orario (mattino/pomeriggio/sera)

3

🔗 Collega l'Evento Tick

📝 Procedura:

  1. Seleziona il Timer nella parte bassa del Designer
  2. Premi F4 per aprire Properties
  3. Clicca sull'icona del fulmine ⚡ (Eventi)
  4. Trova l'evento Tick
  5. Fai doppio click → Visual Studio crea il metodo

📚 Concetti Chiave - DateTime

DateTime.Now
Ottiene la data e ora corrente del sistema

DateTime adesso = DateTime.Now;

Console.WriteLine(adesso.Hour);        // 14 (ore)
Console.WriteLine(adesso.Minute);      // 30 (minuti)
Console.WriteLine(adesso.Second);      // 45 (secondi)
Console.WriteLine(adesso.Day);         // 15 (giorno)
Console.WriteLine(adesso.Month);       // 1 (gennaio)
Console.WriteLine(adesso.Year);        // 2025

DateTime.ToString(formato)
Formatta data/ora in vari modi

DateTime dt = DateTime.Now;

dt.ToString("HH:mm:ss")           // "14:30:45" (24 ore)
dt.ToString("hh:mm:ss tt")        // "02:30:45 PM" (12 ore)
dt.ToString("dd/MM/yyyy")         // "15/01/2025"
dt.ToString("dddd, dd MMMM yyyy") // "mercoledì, 15 gennaio 2025"
dt.ToString("yyyy-MM-dd")         // "2025-01-15" (formato ISO)

Timer.Start() e .Stop()
Avvia e ferma il timer

timer.Start();    // Inizia a contare
timer.Stop();     // Si ferma
timer.Enabled = true;  // Equivalente a Start()
timer.Enabled = false; // Equivalente a Stop()

⏱️ Esercizio 2: Cronometro

▶ Obiettivo

Crea un cronometro con pulsanti Start, Stop e Reset!
Conta i secondi che passano e puoi fermarlo quando vuoi! ⏱️

1

Interfaccia

  • Label: lbl_cronometro (Text = "00:00:00", Font grande)
  • Button: btn_start (Text = "▶ Start")
  • Button: btn_stop (Text = "⏸ Stop", Enabled = false)
  • Button: btn_reset (Text = "🔄 Reset")
  • Timer: timer_cronometro (Interval = 100, Enabled = false)

2

Codice Completo

Cronometro.cs
using System;
using System.Windows.Forms;

namespace Cronometro
{
    public partial class Form1 : Form
    {
        // Variabile per tenere traccia dei millisecondi
        private int millisecondi = 0;

        public Form1()
        {
            InitializeComponent();
        }

        // ═══════════════════════════════════════════
        // PULSANTE: START
        // ═══════════════════════════════════════════
        private void btn_start_Click(object sender, EventArgs e)
        {
            // Avvia il timer
            timer_cronometro.Start();
            
            // Disabilita Start, abilita Stop
            btn_start.Enabled = false;
            btn_stop.Enabled = true;
        }

        // ═══════════════════════════════════════════
        // PULSANTE: STOP
        // ═══════════════════════════════════════════
        private void btn_stop_Click(object sender, EventArgs e)
        {
            // Ferma il timer
            timer_cronometro.Stop();
            
            // Abilita Start, disabilita Stop
            btn_start.Enabled = true;
            btn_stop.Enabled = false;
        }

        // ═══════════════════════════════════════════
        // PULSANTE: RESET
        // ═══════════════════════════════════════════
        private void btn_reset_Click(object sender, EventArgs e)
        {
            // Ferma il timer
            timer_cronometro.Stop();
            
            // Resetta a zero
            millisecondi = 0;
            
            // Aggiorna display
            AggiornaDisplay();
            
            // Abilita Start, disabilita Stop
            btn_start.Enabled = true;
            btn_stop.Enabled = false;
        }

        // ═══════════════════════════════════════════
        // TIMER TICK: Ogni 100ms (0.1 secondi)
        // ═══════════════════════════════════════════
        private void timer_cronometro_Tick(object sender, EventArgs e)
        {
            // Incrementa di 100 millisecondi
            millisecondi += 100;
            
            // Aggiorna il display
            AggiornaDisplay();
        }

        // ═══════════════════════════════════════════
        // AGGIORNA IL DISPLAY
        // ═══════════════════════════════════════════
        private void AggiornaDisplay()
        {
            // Converti millisecondi in ore:minuti:secondi
            
            int totaleSecondi = millisecondi / 1000;
            
            int ore = totaleSecondi / 3600;
            int minuti = (totaleSecondi % 3600) / 60;
            int secondi = totaleSecondi % 60;
            int decimi = (millisecondi % 1000) / 100;
            
            // Formatta come HH:MM:SS.d
            lbl_cronometro.Text = string.Format("{0:00}:{1:00}:{2:00}.{3}", 
                                               ore, minuti, secondi, decimi);
        }
    }
}

3

🎬 Come Funziona

📋 Flusso:

  1. All'avvio: cronometro fermo a 00:00:00.0
  2. Clicchi Start → timer si avvia
  3. Ogni 0.1 secondi (100ms) → millisecondi += 100
  4. Il display si aggiorna: 00:00:00.1, 00:00:00.2, ... 00:00:01.0, ecc.
  5. Clicchi Stop → si ferma dove è arrivato
  6. Clicchi Reset → torna a 00:00:00.0

📚 Operazioni Matematiche Utili

Operatore % (modulo)
Restituisce il resto della divisione

10 % 3 = 1   // 10 diviso 3 = 3 con resto 1
15 % 4 = 3   // 15 diviso 4 = 3 con resto 3
100 % 60 = 40  // 100 secondi = 1 minuto e 40 secondi

// Uso pratico: convertire secondi in minuti
int totaleSecondi = 150;
int minuti = totaleSecondi / 60;      // 2 minuti
int secondi = totaleSecondi % 60;     // 30 secondi

string.Format()
Formatta stringhe con placeholder e padding

int ore = 5, minuti = 7, secondi = 9;

// Senza Format (brutto)
string tempo = ore + ":" + minuti + ":" + secondi;  // "5:7:9"

// Con Format e padding (bello!)
string tempo = string.Format("{0:00}:{1:00}:{2:00}", ore, minuti, secondi);
// Risultato: "05:07:09"

// {0:00} significa: prendi il primo parametro e mostralo con 2 cifre

📊 ProgressBar: Barra di Progresso

🤔 Cos'è la ProgressBar?

Hai presente quando installi un programma e vedi la barra che si riempie?
"Download in corso... 47% ▰▰▰▰▱▱▱▱▱▱" Quella è una ProgressBar!
Mostra visivamente quanto manca al completamento.

⚙️ Proprietà Principali

  • Minimum: Valore minimo (di solito 0)
  • Maximum: Valore massimo (es: 100 per percentuale)
  • Value: Valore attuale (da Minimum a Maximum)
  • Style: Blocks (a blocchi) o Continuous (continua)
📊 Esempio Pratico:

Minimum = 0
Maximum = 100
Value = 47

Barra al 47%: ▰▰▰▰▰▱▱▱▱▱

🍅 Esercizio 3: Pomodoro Technique Timer

▶ Obiettivo

Crea un timer per la Pomodoro Technique: 25 minuti di lavoro,
poi 5 minuti di pausa. Con ProgressBar che mostra quanto manca! 🍅

📖 Cos'è la Pomodoro Technique?

Tecnica di produttività: lavori concentrato per 25 minuti,
poi ti premi con 5 minuti di pausa. Si ripete! Super efficace per studiare!

1

Interfaccia

  • Label: lbl_stato (Text = "LAVORO", Font grande, Bold)
  • Label: lbl_tempo (Text = "25:00", Font molto grande)
  • ProgressBar: progressBar (Minimum = 0, Maximum = 100)
  • Button: btn_start (Text = "▶ Inizia")
  • Button: btn_pausa (Text = "⏸ Pausa", Enabled = false)
  • Button: btn_reset (Text = "🔄 Reset")
  • Timer: timer (Interval = 1000, Enabled = false)

2

Codice Completo

PomodoroTimer.cs
using System;
using System.Drawing;
using System.Windows.Forms;

namespace PomodoroTimer
{
    public partial class Form1 : Form
    {
        // Costanti (tempo in secondi)
        private const int TEMPO_LAVORO = 25 * 60;    // 25 minuti = 1500 secondi
        private const int TEMPO_PAUSA = 5 * 60;      // 5 minuti = 300 secondi

        // Variabili di stato
        private int secondiRimanenti;
        private int secondiTotali;
        private bool modalitaLavoro = true;  // true = lavoro, false = pausa

        public Form1()
        {
            InitializeComponent();
            
            // Inizializza con modalità lavoro
            ImpostaModalitaLavoro();
        }

        // ═══════════════════════════════════════════
        // IMPOSTA MODALITÀ LAVORO
        // ═══════════════════════════════════════════
        private void ImpostaModalitaLavoro()
        {
            modalitaLavoro = true;
            secondiRimanenti = TEMPO_LAVORO;
            secondiTotali = TEMPO_LAVORO;
            
            lbl_stato.Text = "⏰ TEMPO DI LAVORO";
            lbl_stato.ForeColor = Color.Green;
            this.BackColor = Color.LightGreen;
            
            AggiornaDisplay();
        }

        // ═══════════════════════════════════════════
        // IMPOSTA MODALITÀ PAUSA
        // ═══════════════════════════════════════════
        private void ImpostaModalitaPausa()
        {
            modalitaLavoro = false;
            secondiRimanenti = TEMPO_PAUSA;
            secondiTotali = TEMPO_PAUSA;
            
            lbl_stato.Text = "☕ TEMPO DI PAUSA";
            lbl_stato.ForeColor = Color.Blue;
            this.BackColor = Color.LightBlue;
            
            AggiornaDisplay();
        }

        // ═══════════════════════════════════════════
        // PULSANTE: START
        // ═══════════════════════════════════════════
        private void btn_start_Click(object sender, EventArgs e)
        {
            timer.Start();
            btn_start.Enabled = false;
            btn_pausa.Enabled = true;
        }

        // ═══════════════════════════════════════════
        // PULSANTE: PAUSA
        // ═══════════════════════════════════════════
        private void btn_pausa_Click(object sender, EventArgs e)
        {
            timer.Stop();
            btn_start.Enabled = true;
            btn_pausa.Enabled = false;
        }

        // ═══════════════════════════════════════════
        // PULSANTE: RESET
        // ═══════════════════════════════════════════
        private void btn_reset_Click(object sender, EventArgs e)
        {
            timer.Stop();
            ImpostaModalitaLavoro();
            btn_start.Enabled = true;
            btn_pausa.Enabled = false;
        }

        // ═══════════════════════════════════════════
        // TIMER TICK: Ogni secondo
        // ═══════════════════════════════════════════
        private void timer_Tick(object sender, EventArgs e)
        {
            // Decrementa il tempo
            secondiRimanenti--;
            
            // Aggiorna il display
            AggiornaDisplay();
            
            // Controlla se è finito
            if (secondiRimanenti <= 0)
            {
                timer.Stop();
                
                // Suono di notifica
                System.Media.SystemSounds.Beep.Play();
                
                // Cambia modalità
                if (modalitaLavoro)
                {
                    // Finito il lavoro → inizia pausa
                    MessageBox.Show("⏰ Tempo scaduto!\n\nHai lavorato per 25 minuti.\nAdesso 5 minuti di pausa! ☕", 
                                  "Pomodoro", 
                                  MessageBoxButtons.OK, 
                                  MessageBoxIcon.Information);
                    
                    ImpostaModalitaPausa();
                }
                else
                {
                    // Finita la pausa → inizia lavoro
                    MessageBox.Show("☕ Pausa finita!\n\nTorna al lavoro per altri 25 minuti! 💪", 
                                  "Pomodoro", 
                                  MessageBoxButtons.OK, 
                                  MessageBoxIcon.Information);
                    
                    ImpostaModalitaLavoro();
                }
                
                btn_start.Enabled = true;
                btn_pausa.Enabled = false;
            }
        }

        // ═══════════════════════════════════════════
        // AGGIORNA DISPLAY
        // ═══════════════════════════════════════════
        private void AggiornaDisplay()
        {
            // Converti in minuti:secondi
            int minuti = secondiRimanenti / 60;
            int secondi = secondiRimanenti % 60;
            
            // Mostra il tempo
            lbl_tempo.Text = string.Format("{0:00}:{1:00}", minuti, secondi);
            
            // Aggiorna la ProgressBar
            // Calcola percentuale completata
            int percentualeCompletata = (int)(((double)(secondiTotali - secondiRimanenti) / secondiTotali) * 100);
            progressBar.Value = Math.Min(percentualeCompletata, 100);
            
            // BONUS: Colore della progressbar in base al tempo rimasto
            if (secondiRimanenti < 60)
            {
                // Ultimi 60 secondi → rosso (urgente!)
                progressBar.ForeColor = Color.Red;
            }
            else if (secondiRimanenti < 300)
            {
                // Ultimi 5 minuti → arancione
                progressBar.ForeColor = Color.Orange;
            }
            else
            {
                // Tanto tempo → verde
                progressBar.ForeColor = Color.Green;
            }
        }
    }
}

3

🎬 Come Funziona

📋 Ciclo Pomodoro:

  1. App si apre in modalità LAVORO (sfondo verde, 25:00)
  2. Clicchi Inizia → il countdown parte
  3. La ProgressBar si riempie man mano
  4. Arriva a 00:00 → BEEP! MessageBox: "Tempo scaduto!"
  5. Passa in modalità PAUSA (sfondo blu, 05:00)
  6. Clicchi Inizia di nuovo → countdown pausa
  7. Arriva a 00:00 → BEEP! Torna in modalità LAVORO
  8. Il ciclo continua!

📚 Nuovi Concetti

System.Media.SystemSounds.Beep.Play()
Riproduce un suono di sistema

// Suono beep standard
SystemSounds.Beep.Play();

// Altri suoni disponibili:
SystemSounds.Asterisk.Play();     // *
SystemSounds.Exclamation.Play();  // !
SystemSounds.Hand.Play();         // ✋
SystemSounds.Question.Play();     // ?

Math.Min() e Math.Max()
Restituisce il valore minimo o massimo tra due numeri

int minore = Math.Min(5, 10);    // 5
int maggiore = Math.Max(5, 10);  // 10

// Uso pratico: limita un valore
progressBar.Value = Math.Min(percentuale, 100); 
// Se percentuale = 150, Value sarà 100 (limite massimo)

Const (costanti)
Valori che non cambiano mai durante l'esecuzione

// Dichiarazione costante
private const int TEMPO_LAVORO = 1500;

// Convenzione: NOME_TUTTO_MAIUSCOLO
// Vantaggi: più leggibile, se cambi valore è in UN solo punto

📥 Esercizio 4: Simulatore Download

▶ Obiettivo

Simula il download di un file con ProgressBar che si riempie e percentuale che sale!

1

Interfaccia Veloce

  • ProgressBar: progressBar
  • Label: lbl_percentuale (Text = "0%")
  • Label: lbl_stato (Text = "Pronto")
  • Button: btn_download (Text = "📥 Scarica File")
  • Timer: timer (Interval = 100, Enabled = false)

2

Codice Semplificato

DownloadSimulator.cs
private int percentuale = 0;

private void btn_download_Click(object sender, EventArgs e)
{
    // Reset
    percentuale = 0;
    progressBar.Value = 0;
    lbl_stato.Text = "Download in corso...";
    
    // Avvia timer
    timer.Start();
    
    // Disabilita pulsante
    btn_download.Enabled = false;
}

private void timer_Tick(object sender, EventArgs e)
{
    // Incrementa percentuale (random per simulare velocità variabile)
    Random rnd = new Random();
    int incremento = rnd.Next(1, 5);  // Da 1 a 4
    
    percentuale += incremento;
    
    // Limita a 100
    if (percentuale > 100)
        percentuale = 100;
    
    // Aggiorna UI
    progressBar.Value = percentuale;
    lbl_percentuale.Text = $"{percentuale}%";
    
    // Download completato?
    if (percentuale >= 100)
    {
        timer.Stop();
        lbl_stato.Text = "✅ Download completato!";
        lbl_stato.ForeColor = Color.Green;
        btn_download.Enabled = true;
        
        MessageBox.Show("File scaricato con successo!", "Completato", 
                      MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

❓ Esercizio 5: Quiz a Tempo

▶ Obiettivo

Quiz con domande a risposta multipla. Hai 30 secondi per rispondere!

1

Codice Completo (Semplificato)

QuizATempo.cs
private int tempoRimasto = 30;
private int domandaCorrente = 0;
private int punteggioTotale = 0;

private string[] domande = {
    "Quale linguaggio usiamo?",
    "Quanti millisecondi in 1 secondo?",
    "Che controllo mostra tabelle?"
};

private string[][] opzioni = {
    new string[] { "C#", "Python", "Java", "Ruby" },
    new string[] { "10", "100", "1000", "10000" },
    new string[] { "Label", "TextBox", "DataGridView", "Button" }
};

private int[] risposteCorrette = { 0, 2, 2 }; // Indici delle risposte corrette

private void btn_inizia_Click(object sender, EventArgs e)
{
    domandaCorrente = 0;
    punteggioTotale = 0;
    MostraDomanda();
}

private void MostraDomanda()
{
    if (domandaCorrente >= domande.Length)
    {
        // Quiz finito!
        timer.Stop();
        MessageBox.Show($"Quiz completato!\nPunteggio: {punteggioTotale}/{domande.Length}", 
                       "Fine", MessageBoxButtons.OK, MessageBoxIcon.Information);
        return;
    }

    // Mostra domanda
    lbl_domanda.Text = domande[domandaCorrente];
    
    // Mostra opzioni (4 RadioButton)
    rdb_opzione1.Text = opzioni[domandaCorrente][0];
    rdb_opzione2.Text = opzioni[domandaCorrente][1];
    rdb_opzione3.Text = opzioni[domandaCorrente][2];
    rdb_opzione4.Text = opzioni[domandaCorrente][3];
    
    // Reset timer
    tempoRimasto = 30;
    progressBar.Maximum = 30;
    progressBar.Value = 30;
    timer.Start();
}

private void timer_Tick(object sender, EventArgs e)
{
    tempoRimasto--;
    progressBar.Value = tempoRimasto;
    lbl_tempo.Text = $"Tempo: {tempoRimasto}s";
    
    if (tempoRimasto <= 0)
    {
        timer.Stop();
        MessageBox.Show("Tempo scaduto!", "Oops", 
                      MessageBoxButtons.OK, MessageBoxIcon.Warning);
        domandaCorrente++;
        MostraDomanda();
    }
}

private void btn_risposta_Click(object sender, EventArgs e)
{
    timer.Stop();
    
    // Controlla quale RadioButton è selezionato
    int rispostaData = -1;
    if (rdb_opzione1.Checked) rispostaData = 0;
    else if (rdb_opzione2.Checked) rispostaData = 1;
    else if (rdb_opzione3.Checked) rispostaData = 2;
    else if (rdb_opzione4.Checked) rispostaData = 3;
    
    // Verifica correttezza
    if (rispostaData == risposteCorrette[domandaCorrente])
    {
        punteggioTotale++;
        MessageBox.Show("✅ Risposta corretta!", "Bravo!", 
                      MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    else
    {
        MessageBox.Show("❌ Risposta sbagliata!", "Oops", 
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    
    domandaCorrente++;
    MostraDomanda();
}

🎓 Riepilogo: Cosa Hai Imparato

✨ Competenze Acquisite

1️⃣ Timer

  • Eseguire codice periodicamente
  • Creare orologi e cronometri
  • Start(), Stop(), Interval
2️⃣ ProgressBar

  • Mostrare avanzamento
  • Feedback visivo operazioni
  • Minimum, Maximum, Value
3️⃣ DateTime

  • Ottenere data/ora corrente
  • Formattare orari
  • Calcoli con tempo
4️⃣ Applicazioni Dinamiche

  • Countdown e timer
  • Simulazioni real-time
  • Quiz interattivi

🚀 Prossima Lezione

Hai imparato a creare app dinamiche! Nella prossima lezione scoprirai come
creare applicazioni multi-finestra: form di login che aprono
dashboard, finestre di dettaglio, dialog personalizzati! 🪟

Torna in alto