🎮 Controlli Avanzati in Windows Forms

Crea interfacce professionali con RadioButton, CheckBox, Menu e Immagini

🎯 Cosa Imparerai in Questa Lezione

Congratulazioni per essere arrivato fin qui! Hai già imparato a gestire TextBox,
ListBox, ComboBox e gli eventi multipli.
Ora è il momento di scoprire controlli ancora più potenti che renderanno le tue applicazioni
davvero professionali! 🚀

✨ I Nuovi Controlli che Padroneggerai

🔘 RadioButton

Scelta esclusiva: puoi selezionare SOLO UNA opzione alla volta
(es: Maschio/Femmina, Piccola/Media/Grande)

☑️ CheckBox

Scelta multipla: puoi selezionare QUANTE vuoi
(es: RGB, SSD, WiFi, Bluetooth – tutte insieme!)

📋 MenuStrip

Menu professionale in alto come Word/Excel
(File → Nuovo, Modifica → Copia, ecc.)

🖼️ PictureBox

Mostra immagini nella tua app: loghi, foto prodotti,
icone, qualsiasi immagine!

📚 Prerequisiti

Prima di iniziare, dovresti aver completato:

  • ✅ TextBox e Label
  • ✅ ListBox e ComboBox
  • ✅ Gestione Eventi Multipli

Se hai fatto questi, sei pronto per creare app ancora più fighe!

🤔 RadioButton vs CheckBox: Qual è la Differenza?

🔘 RadioButton

UNA SOLA SCELTA

◉ Piccola

◯ Media

◯ Grande

💡 Quando usarlo:

  • Taglia vestiti
  • Maschio/Femmina
  • Scelta processore (i5/i7/i9)
  • Livello difficoltà
⚡ Regola: Se selezioni “Media”, “Piccola” e “Grande”
si deselezioneranno automaticamente

☑️ CheckBox

PIÙ SCELTE INSIEME

☑ Luci RGB

☑ SSD NVMe

☐ WiFi 6

☑ Bluetooth

💡 Quando usarlo:

  • Opzioni PC (RGB, SSD, WiFi)
  • Giorni allenamento
  • Servizi extra viaggio
  • Ingredienti pizza
⚡ Regola: Puoi selezionare TUTTE
le opzioni che vuoi, sono indipendenti!

🎯 Trucco per Ricordare:

RadioButton = Canali radio (ne ascolti UNO alla volta)
CheckBox = Carrello spesa (metti TUTTO quello che vuoi)

🎮 Esercizio 1: Configuratore PC Gaming

▶ Obiettivo

Crea un’applicazione dove l’utente può configurare il proprio PC Gaming
scegliendo processore, scheda video e opzioni extra. L’app calcola automaticamente il
prezzo totale!

🎯 Cosa Imparerai:

  • Usare RadioButton per scelta esclusiva (un solo processore)
  • Usare CheckBox per opzioni multiple (RGB + SSD + altro)
  • Creare un Menu professionale in alto
  • Mostrare immagini di prodotti
  • Calcolare prezzi e formattarli come € 1.250,00

1

Crea l’Interfaccia Passo-Passo

🔧 Controlli da Aggiungere:

1️⃣ GroupBox “Processore” con RadioButton:

  • rdb_i5 (testo: “Intel i5 – €250”)
  • rdb_i7 (testo: “Intel i7 – €400”)
  • rdb_i9 (testo: “Intel i9 – €600”)
  • rdb_ryzen7 (testo: “AMD Ryzen 7 – €350”)

💡 Il GroupBox raggruppa i RadioButton, così puoi selezionarne uno solo

2️⃣ GroupBox “Scheda Video” con RadioButton:

  • rdb_rtx3060 (testo: “RTX 3060 – €350”)
  • rdb_rtx4070 (testo: “RTX 4070 – €650”)
  • rdb_rtx4090 (testo: “RTX 4090 – €1200”)

3️⃣ GroupBox “Opzioni Extra” con CheckBox:

  • chk_rgb (testo: “Luci RGB – €80”)
  • chk_watercooling (testo: “Raffreddamento a Liquido – €120”)
  • chk_ssd_nvme (testo: “SSD NVMe 1TB – €150”)

💡 Qui puoi selezionare TUTTE le opzioni che vuoi!

4️⃣ Altri Controlli:

  • Button: btn_calcola_prezzo (testo: “Calcola Prezzo”)
  • Label: lbl_prezzo_totale (testo: “€ 0,00”, font grande, bold)
  • PictureBox: pic_pc_gaming (per immagine PC)

5️⃣ MenuStrip (in alto):

  • FileNuova Configurazione
  • FileEsci

💡 Come creare il menu: Trascina “MenuStrip” dalla Toolbox,
poi clicca su “File” e aggiungi le voci

2

Il Codice Completo Spiegato

ConfiguratorePCGaming.cs
using System;
using System.Windows.Forms;

namespace ConfiguratorePCGaming
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
            // Seleziona opzioni di default all'avvio
            rdb_i5.Checked = true;
            rdb_rtx3060.Checked = true;
        }

        // ========================================
        // METODO: Calcola il prezzo totale
        // ========================================
        private void btn_calcola_prezzo_Click(object sender, EventArgs e)
        {
            // Usa decimal per i prezzi (più preciso di double)
            decimal prezzo_totale = 0;

            try
            {
                // ═════════════════════════════════
                // 1️⃣ CALCOLA PREZZO PROCESSORE
                // ═════════════════════════════════
                // Solo UNO sarà selezionato (RadioButton)
                if (rdb_i5.Checked)
                    prezzo_totale += 250;
                else if (rdb_i7.Checked)
                    prezzo_totale += 400;
                else if (rdb_i9.Checked)
                    prezzo_totale += 600;
                else if (rdb_ryzen7.Checked)
                    prezzo_totale += 350;

                // ═════════════════════════════════
                // 2️⃣ CALCOLA PREZZO SCHEDA VIDEO
                // ═════════════════════════════════
                // Anche qui solo UNA scheda video
                if (rdb_rtx3060.Checked)
                    prezzo_totale += 350;
                else if (rdb_rtx4070.Checked)
                    prezzo_totale += 650;
                else if (rdb_rtx4090.Checked)
                    prezzo_totale += 1200;

                // ═════════════════════════════════
                // 3️⃣ CALCOLA OPZIONI EXTRA
                // ═════════════════════════════════
                // Qui possono essere selezionate TUTTE (CheckBox)
                if (chk_rgb.Checked)
                    prezzo_totale += 80;
                
                if (chk_watercooling.Checked)
                    prezzo_totale += 120;
                
                if (chk_ssd_nvme.Checked)
                    prezzo_totale += 150;

                // ═════════════════════════════════
                // 4️⃣ MOSTRA IL RISULTATO FORMATTATO
                // ═════════════════════════════════
                // ToString("C") formatta come valuta: € 1.250,00
                lbl_prezzo_totale.Text = prezzo_totale.ToString("C");
                lbl_prezzo_totale.ForeColor = Color.Green;
            }
            catch (Exception ex)
            {
                // Se qualcosa va storto, mostra l'errore
                MessageBox.Show("Errore nel calcolo: " + ex.Message, 
                              "Errore",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Error);
            }
        }

        // ========================================
        // MENU: Nuova Configurazione
        // ========================================
        private void nuovaConfigurazioneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Resetta tutto allo stato iniziale
            rdb_i5.Checked = true;
            rdb_rtx3060.Checked = true;
            chk_rgb.Checked = false;
            chk_watercooling.Checked = false;
            chk_ssd_nvme.Checked = false;
            lbl_prezzo_totale.Text = "€ 0,00";
            lbl_prezzo_totale.ForeColor = Color.Black;
            
            MessageBox.Show("Configurazione resettata!", 
                          "Info", 
                          MessageBoxButtons.OK, 
                          MessageBoxIcon.Information);
        }

        // ========================================
        // MENU: Esci dall'applicazione
        // ========================================
        private void esciToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Chiedi conferma prima di chiudere
            DialogResult risultato = MessageBox.Show(
                "Sei sicuro di voler uscire?", 
                "Conferma Uscita",
                MessageBoxButtons.YesNo, 
                MessageBoxIcon.Question);
            
            if (risultato == DialogResult.Yes)
            {
                Application.Exit(); // Chiudi l'applicazione
            }
        }
    }
}

3

🎬 Come Funziona? (Esempio Pratico)

📋 Scenario: Configurazione PC Gaming

1️⃣ L’utente seleziona:

  • ◉ Intel i7 (€400)
  • ◉ RTX 4070 (€650)
  • ☑ Luci RGB (€80)
  • ☑ SSD NVMe (€150)

2️⃣ Clicca “Calcola Prezzo”

Il codice calcola:
400 + 650 + 80 + 150 = €1.280,00

3️⃣ Risultato mostrato:

€ 1.280,00

💡 Nota: Se cambi processore da i7 a i9, devi
cliccare di nuovo “Calcola Prezzo” per vedere il nuovo totale.

4

🎨 Miglioria: Calcolo Automatico in Tempo Reale

Vuoi che il prezzo si aggiorni automaticamente senza cliccare il pulsante? Ecco come:

Versione con Aggiornamento Automatico
// Metodo che calcola e aggiorna automaticamente
private void AggiornaPrezzoAutomatico()
{
    decimal prezzo_totale = 0;

    // Processore
    if (rdb_i5.Checked) prezzo_totale += 250;
    else if (rdb_i7.Checked) prezzo_totale += 400;
    else if (rdb_i9.Checked) prezzo_totale += 600;
    else if (rdb_ryzen7.Checked) prezzo_totale += 350;

    // Scheda Video
    if (rdb_rtx3060.Checked) prezzo_totale += 350;
    else if (rdb_rtx4070.Checked) prezzo_totale += 650;
    else if (rdb_rtx4090.Checked) prezzo_totale += 1200;

    // Opzioni
    if (chk_rgb.Checked) prezzo_totale += 80;
    if (chk_watercooling.Checked) prezzo_totale += 120;
    if (chk_ssd_nvme.Checked) prezzo_totale += 150;

    lbl_prezzo_totale.Text = prezzo_totale.ToString("C");
}

// Collegare questo metodo a TUTTI i RadioButton e CheckBox!
// Evento CheckedChanged per ogni controllo:
private void ControlloQualsiasi_CheckedChanged(object sender, EventArgs e)
{
    AggiornaPrezzoAutomatico();
}

// Nel Designer: Collega CheckedChanged di TUTTI i controlli a questo metodo!

✨ Risultato: Ora il prezzo si aggiorna in tempo reale
appena cambi un’opzione, senza dover cliccare alcun pulsante!

📚 Concetti Chiave dell’Esercizio 1

decimal (tipo per soldi)
Tipo di dato speciale per calcoli monetari. Più preciso di double
perché non ha errori di arrotondamento.

// Usa decimal per i soldi
decimal prezzo = 250.50m;  // La "m" alla fine = decimal

// SBAGLIATO con double:
double prezzo1 = 0.1 + 0.2; // = 0.30000000000000004 😱

// GIUSTO con decimal:
decimal prezzo2 = 0.1m + 0.2m; // = 0.3 ✅

.ToString(“C”) – Formato Valuta
Converte un numero in formato valuta con simbolo € e decimali

decimal numero = 1250.50m;

numero.ToString()      // "1250.5"
numero.ToString("C")   // "€ 1.250,50" (in Italia)
numero.ToString("C0")  // "€ 1.251" (senza decimali)
numero.ToString("F2")  // "1250.50" (senza €)

DialogResult (conferme)
Usato per sapere quale pulsante l’utente ha cliccato in un MessageBox

DialogResult risultato = MessageBox.Show(
    "Sei sicuro?", 
    "Conferma",
    MessageBoxButtons.YesNo,
    MessageBoxIcon.Question);

if (risultato == DialogResult.Yes)
{
    // L'utente ha cliccato SÌ
}
else
{
    // L'utente ha cliccato NO
}

Application.Exit()
Chiude completamente l’applicazione Windows Forms

Application.Exit(); // Chiude tutto

💪 Esercizio 2: Generatore Piano di Allenamento

▶ Obiettivo

Crea un’app che genera un piano di allenamento personalizzato in base a:
livello (principiante/intermedio/avanzato), obiettivo (forza/dimagrimento/resistenza)
e giorni della settimana selezionati!

🎯 Novità in Questo Esercizio:

  • Usare StringBuilder per costruire testo lungo
  • Generare contenuto dinamico in base alle scelte
  • Mostrare risultati in una TextBox multiriga
  • Validare che l’utente abbia fatto tutte le selezioni necessarie


Piano di Allenamento

1

Interfaccia da Creare

  • GroupBox “Livello” con RadioButton:
    • rdb_principiante
    • rdb_intermedio
    • rdb_avanzato
  • GroupBox “Obiettivo” con RadioButton:
    • rdb_forza
    • rdb_dimagrimento
    • rdb_resistenza
  • GroupBox “Giorni Allenamento” con CheckBox:
    • chk_lunedi, chk_martedi, chk_mercoledi, ecc.
  • Button: btn_genera_allenamento
  • TextBox: txt_piano (Multiline = true, ScrollBars = Vertical)

2

Codice Semplificato con Spiegazioni

GeneratorePianoAllenamento.cs
using System;
using System.Text; // Per usare StringBuilder
using System.Windows.Forms;

namespace PianoAllenamento
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // ========================================
        // GENERA IL PIANO DI ALLENAMENTO
        // ========================================
        private void btn_genera_allenamento_Click(object sender, EventArgs e)
        {
            // 1️⃣ Controlla che l'utente abbia selezionato livello e obiettivo
            if (!VerificaSelezioni())
            {
                MessageBox.Show("⚠️ Seleziona livello e obiettivo!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return; // Esci dal metodo
            }

            // 2️⃣ Crea il piano usando StringBuilder
            StringBuilder piano = new StringBuilder();

            // Intestazione
            piano.AppendLine("════════════════════════════════════════");
            piano.AppendLine("   📋 PIANO ALLENAMENTO PERSONALIZZATO");
            piano.AppendLine("════════════════════════════════════════");
            piano.AppendLine();
            piano.AppendLine($"👤 Livello: {OttieniLivello()}");
            piano.AppendLine($"🎯 Obiettivo: {OttieniObiettivo()}");
            piano.AppendLine();
            piano.AppendLine("────────────────────────────────────────");
            piano.AppendLine();

            // 3️⃣ Genera i giorni selezionati
            GeneraGiorniAllenamento(piano);

            // 4️⃣ Mostra il risultato nella TextBox
            txt_piano.Text = piano.ToString();
        }

        // ========================================
        // VERIFICA CHE LIVELLO E OBIETTIVO SIANO SELEZIONATI
        // ========================================
        private bool VerificaSelezioni()
        {
            // Verifica almeno un livello
            bool livelloOk = rdb_principiante.Checked || 
                           rdb_intermedio.Checked || 
                           rdb_avanzato.Checked;

            // Verifica almeno un obiettivo
            bool obiettivoOk = rdb_forza.Checked || 
                             rdb_dimagrimento.Checked || 
                             rdb_resistenza.Checked;

            return livelloOk && obiettivoOk;
        }

        // ========================================
        // OTTIENI IL LIVELLO SELEZIONATO
        // ========================================
        private string OttieniLivello()
        {
            if (rdb_principiante.Checked) return "Principiante";
            if (rdb_intermedio.Checked) return "Intermedio";
            if (rdb_avanzato.Checked) return "Avanzato";
            return "Non specificato";
        }

        // ========================================
        // OTTIENI L'OBIETTIVO SELEZIONATO
        // ========================================
        private string OttieniObiettivo()
        {
            if (rdb_forza.Checked) return "Forza Muscolare";
            if (rdb_dimagrimento.Checked) return "Dimagrimento";
            if (rdb_resistenza.Checked) return "Resistenza";
            return "Non specificato";
        }

        // ========================================
        // GENERA GLI ESERCIZI PER I GIORNI SELEZIONATI
        // ========================================
        private void GeneraGiorniAllenamento(StringBuilder piano)
        {
            // Array con esercizi
            string[] esercizi = { 
                "Squat", 
                "Panca piana", 
                "Stacchi da terra", 
                "Military Press", 
                "Rematore con bilanciere" 
            };

            // Calcola ripetizioni in base al livello
            int ripetizioni = OttieniRipetizioni();

            // ═══════════════════════════
            // LUNEDÌ
            // ═══════════════════════════
            if (chk_lunedi.Checked)
            {
                piano.AppendLine("📅 LUNEDÌ - Gambe e Petto");
                piano.AppendLine($"   • {esercizi[0]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine($"   • {esercizi[1]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine();
            }

            // ═══════════════════════════
            // MERCOLEDÌ
            // ═══════════════════════════
            if (chk_mercoledi.Checked)
            {
                piano.AppendLine("📅 MERCOLEDÌ - Schiena e Spalle");
                piano.AppendLine($"   • {esercizi[2]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine($"   • {esercizi[3]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine();
            }

            // ═══════════════════════════
            // VENERDÌ
            // ═══════════════════════════
            if (chk_venerdi.Checked)
            {
                piano.AppendLine("📅 VENERDÌ - Full Body");
                piano.AppendLine($"   • {esercizi[0]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine($"   • {esercizi[4]} - 3 serie x {ripetizioni} ripetizioni");
                piano.AppendLine();
            }

            // Aggiungi altri giorni se vuoi...

            piano.AppendLine("════════════════════════════════════════");
            piano.AppendLine("💪 Buon allenamento!");
        }

        // ========================================
        // CALCOLA RIPETIZIONI IN BASE AL LIVELLO
        // ========================================
        private int OttieniRipetizioni()
        {
            if (rdb_principiante.Checked) return 8;
            if (rdb_intermedio.Checked) return 10;
            if (rdb_avanzato.Checked) return 12;
            return 8; // Default
        }
    }
}

3

🎬 Esempio di Output Generato

Esempio Risultato
════════════════════════════════════════
   📋 PIANO ALLENAMENTO PERSONALIZZATO
════════════════════════════════════════

👤 Livello: Intermedio
🎯 Obiettivo: Forza Muscolare

────────────────────────────────────────

📅 LUNEDÌ - Gambe e Petto
   • Squat - 3 serie x 10 ripetizioni
   • Panca piana - 3 serie x 10 ripetizioni

📅 MERCOLEDÌ - Schiena e Spalle
   • Stacchi da terra - 3 serie x 10 ripetizioni
   • Military Press - 3 serie x 10 ripetizioni

📅 VENERDÌ - Full Body
   • Squat - 3 serie x 10 ripetizioni
   • Rematore con bilanciere - 3 serie x 10 ripetizioni

════════════════════════════════════════
💪 Buon allenamento!

📚 Concetti Chiave dell’Esercizio 2

StringBuilder
Classe per costruire stringhe lunghe in modo efficiente. Molto meglio di concatenare con +

// ❌ LENTO (crea 3 nuove stringhe!)
string testo = "";
testo += "Riga 1\n";
testo += "Riga 2\n";
testo += "Riga 3\n";

// ✅ VELOCE (StringBuilder)
StringBuilder sb = new StringBuilder();
sb.AppendLine("Riga 1");
sb.AppendLine("Riga 2");
sb.AppendLine("Riga 3");
string risultato = sb.ToString();

.AppendLine()
Aggiunge una riga di testo al StringBuilder con “a capo” automatico

StringBuilder sb = new StringBuilder();
sb.AppendLine("Linea 1"); // Aggiunge "Linea 1\n"
sb.AppendLine("Linea 2"); // Aggiunge "Linea 2\n"
sb.AppendLine();          // Aggiunge solo "\n" (riga vuota)

TextBox Multilinea
Configurare una TextBox per mostrare più righe di testo

// Nel Designer:
// 1. Seleziona la TextBox
// 2. Proprietà → Multiline = true
// 3. Proprietà → ScrollBars = Vertical
// 4. Ridimensiona in altezza

// Nel codice:
txt_piano.Multiline = true;
txt_piano.ScrollBars = ScrollBars.Vertical;
txt_piano.Text = "Riga 1\nRiga 2\nRiga 3";

🎓 Riepilogo: Cosa Hai Imparato

✨ Nuove Competenze Acquisite

1️⃣ RadioButton vs CheckBox

Hai capito la differenza tra scelta esclusiva (RadioButton) e
scelta multipla (CheckBox), e quando usare l’uno o l’altro.

2️⃣ GroupBox per Organizzare

Hai imparato a raggruppare controlli correlati usando GroupBox,
rendendo l’interfaccia più pulita e professionale.

3️⃣ MenuStrip Professionale

Hai creato menu come nelle app professionali (File → Nuovo, Esci)
con gestione delle voci menu.

4️⃣ Calcoli con Decimal

Hai usato il tipo decimal per calcoli monetari precisi e
formattato i prezzi come € 1.250,00.

5️⃣ StringBuilder

Hai scoperto come costruire testi lunghi in modo efficiente
usando StringBuilder invece di concatenare stringhe.

6️⃣ Validazione Robusta

Hai implementato controlli per verificare che l’utente abbia
completato tutte le selezioni necessarie.

💎 Best Practices (Buone Abitudini)

✅ Da Fare

  • Raggruppa con GroupBox: Metti RadioButton correlati nello stesso GroupBox
  • Valida sempre: Controlla che l’utente abbia selezionato tutto il necessario
  • Usa decimal per soldi: Mai usare double o float per prezzi
  • StringBuilder per testi lunghi: Molto più efficiente di +=
  • Nomi descrittivi: rdb_i5, chk_rgb sono chiari

❌ Da Evitare

  • RadioButton senza GroupBox: Non funzionano bene insieme
  • Nessuna validazione: L’app potrebbe crashare
  • double per prezzi: Crea errori di arrotondamento
  • + per testi lunghi: Lentissimo con molte righe
  • Nomi generici: radioButton1 non dice nulla

📋 Tabella Riferimento Rapido

Controllo Quando Usarlo Proprietà Importante Esempio
RadioButton Scelta ESCLUSIVA (una sola) .Checked Taglia vestito, Livello difficoltà
CheckBox Scelte MULTIPLE (anche tutte) .Checked Opzioni extra, Giorni settimana
GroupBox Raggruppare controlli correlati .Text (titolo) Raggruppa RadioButton processore
MenuStrip Menu applicazione professionale Voci del menu File → Nuovo, Esci
PictureBox Mostrare immagini .Image Loghi, foto prodotti, icone
StringBuilder Costruire testi lunghi .AppendLine() Report, piani, elenchi

🏋️ Esercizi per Allenarsi

💪 Sfide Progressive

⭐ Livello Facile:

  1. Crea un configuratore Pizza: scegli dimensione (Piccola/Media/Grande) e ingredienti extra (Mozzarella, Salame, Funghi, ecc.)
  2. Calcola il prezzo totale e mostralo formattato

⭐⭐ Livello Medio:

  1. Crea un configuratore Auto: marca (Fiat/Ford/BMW), optional (Navigatore/Sensori/Tetto), calcola preventivo
  2. Aggiungi immagini diverse per ogni marca di auto
  3. Genera un report dettagliato con StringBuilder

⭐⭐⭐ Livello Difficile:

  1. Crea un generatore di Curriculum Vitae completo
  2. L’utente sceglie template (Classico/Moderno/Creativo), sezioni da includere (Esperienze/Lingue/Hobby)
  3. Genera un CV formattato con StringBuilder e possibilità di salvarlo in file txt
  4. Aggiungi menu per salvare, caricare configurazione precedente

🚀 Prossimi Passi

Hai completato gli esercizi avanzati su Windows Forms! Ora hai tutte le competenze
per creare applicazioni grafiche professionali. Il prossimo step? Approfondire i
fondamenti teorici della programmazione (variabili, operatori, cicli)
per capire ancora meglio come funziona tutto! 🎓

Torna in alto