5. Interfacce grafiche con VB.NET e VS.NET
In questa sede intendiamo illustrare come realizzare interfacce grafiche con VB.NET. Vedremo innanzitutto quali sono le classi di base della piattaforma .NET che ci consentono di realizzare un'interfaccia grafica. In una prima fase non utilizzeremo alcun strumento di generazione automatica. Successivamente utilizzeremo Visual Studio.NET (VS.NET), uno strumento di sviluppo di Microsoft che facilita lo sviluppo di applicazioni con i linguaggi .NET e, in particolare, la creazione di interfacce grafiche. La versione di VS.NET utilizzata è quella in lingua inglese.
5.1. Nozioni di base sulle interfacce grafiche
5.1.1. Una finestra semplice
Consideriamo il seguente codice:
' opzioni
Option Strict On
Option Explicit On
' spazi dei nomi
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' la classe del modulo
Public Class Form1
Inherits Form
' il produttore
Public Sub New()
' titolo della finestra
Me.Text = "Mon premier formulaire"
' dimensioni della finestra
Me.Size = New System.Drawing.Size(300, 100)
End Sub
' funzione di test
Public Shared Sub Main(ByVal args() As String)
' viene visualizzato il modulo
Application.Run(New Form1)
End Sub
End Class
Il codice precedente viene compilato e poi eseguito
L'esecuzione visualizza la seguente finestra:

Un'interfaccia grafica deriva in genere dalla classe base System.Windows.Forms.Form:
La classe base Form definisce una finestra di base con pulsanti di chiusura, ingrandimento/riduzione, dimensioni regolabili, ... e gestisce gli eventi su questi oggetti grafici. Qui specializziamo la classe base assegnandole un titolo e specificandone la larghezza (300) e l'altezza (100). Ciò avviene nel suo costruttore:
Public Sub New()
' titolo della finestra
Me.Text = "Mon premier formulaire"
' dimensioni della finestra
Me.Size = New System.Drawing.Size(300, 100)
End Sub
Il titolo della finestra è definito dalla proprietà Text e le dimensioni dalla proprietà Size. Size è definito nello spazio dei nomi System.Drawing ed è una struttura. La procedura Main avvia l'applicazione grafica nel modo seguente:
Application.Run(New Form1)
Viene creato e visualizzato un modulo di tipo Form1; successivamente, l'applicazione si mette in ascolto degli eventi che si verificano sul modulo (clic, movimenti del mouse, ecc.) e ne esegue quelli gestiti dal modulo stesso. In questo caso, il nostro modulo non gestisce altri eventi oltre a quelli gestiti dalla classe base Form (clic sui pulsanti di chiusura, ingrandimento/riduzione, modifica delle dimensioni della finestra, spostamento della finestra, ecc.).
5.1.2. Un modulo con un pulsante
Aggiungiamo ora un pulsante alla nostra finestra:
' opzioni
Option Strict On
Option Explicit On
' spazi dei nomi
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' classe del modulo
Public Class Form1
Inherits Form
' attributi
Private cmdTest As Button
' il costruttore
Public Sub New()
' il titolo
Me.Text = "Mon premier formulaire"
' le dimensioni
Me.Size = New System.Drawing.Size(300, 100)
' un pulsante
' creazione
Me.cmdTest = New Button
' posizione
cmdTest.Location = New System.Drawing.Point(110, 20)
' dimensioni
cmdTest.Size = New System.Drawing.Size(80, 30)
' etichetta
cmdTest.Text = "Test"
' gestore eventi
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' aggiunta pulsante al modulo
Me.Controls.Add(cmdTest)
End Sub
' gestore eventi
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' è stato cliccato il pulsante - lo si segnala
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' funzione di test
Public Shared Sub Main(ByVal args() As String)
' visualizzazione del modulo
Application.Run(New Form1)
End Sub
End Class
Abbiamo aggiunto un pulsante al modulo:
' un pulsante
' creazione
Me.cmdTest = New Button
' posizione
cmdTest.Location = New System.Drawing.Point(110, 20)
' dimensione
cmdTest.Size = New System.Drawing.Size(80, 30)
' etichetta
cmdTest.Text = "Test"
' gestore eventi
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' aggiunta pulsante al modulo
Me.Controls.Add(cmdTest)
La proprietà Location imposta le coordinate (110,20) del punto in alto a sinistra del pulsante utilizzando una struttura Point. La larghezza e l'altezza del pulsante sono impostate a (80,30) tramite una struttura Size. La proprietà Text del pulsante consente di impostare il testo del pulsante. La classe pulsante possiede un evento Click definito come segue:
dove EventHandler è una funzione «delegata» con la seguente firma:
Ciò significa che il gestore dell'evento [Click] sul pulsante dovrà avere la firma del delegato [EventHandler]. In questo caso, quando si fa clic sul pulsante cmdTest, verrà chiamato il metodo cmdTest_Click. Quest’ultimo è definito come segue, in conformità con il modello precedente EventHandler:
' gestore eventi
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' è stato cliccato il pulsante - lo si segnala
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Ci si limita a visualizzare un messaggio:

La classe viene compilata ed eseguita:
dos>vbc /r:system.dll /r:system.drawing.dll /r:system.windows.forms.dll frm2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>frm2
La classe MessageBox serve a visualizzare messaggi in una finestra. In questo caso abbiamo utilizzato il costruttore
Overloads Public Shared Function Show(ByVal owner As IWin32Window,ByVal text As String,ByVal caption As String,ByVal buttons As MessageBoxButtons,ByVal icon As MessageBoxIcon) As DialogResult
text | il messaggio da visualizzare |
caption | il titolo della finestra |
pulsanti | i pulsanti presenti nella finestra |
icon | l'icona presente nella finestra |
Il parametro buttons può assumere valori tra le seguenti costanti:
costante | pulsanti |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
Il parametro icon può assumere valori tra le seguenti costanti:
![]() | idem Stop | ||
idem Avviso | ![]() | ||
idem Asterisk | ![]() | ||
![]() | idem Hand | ||
![]() |
Il metodo Show è un metodo statico che restituisce un risultato di tipo System.Windows.Forms.DialogResult, che è un'enumerazione:
public enum System.Windows.Forms.DialogResult
{
Abort = 0x00000003,
Cancel = 0x00000002,
Ignore = 0x00000005,
No = 0x00000007,
None = 0x00000000,
OK = 0x00000001,
Retry = 0x00000004,
Yes = 0x00000006,
}
Per sapere quale pulsante ha premuto l'utente per chiudere la finestra di tipo MessageBox, si scriverà:
dim res as DialogResult=MessageBox.Show(..)
if res=DialogResult.Yes then
' ha premuto il pulsante "Sì"
...
end if
5.2. Creazione di un'interfaccia grafica con Visual Studio.NET
Riprendiamo alcuni degli esempi visti in precedenza, realizzandoli ora con Visual Studio.NET.
5.2.1. Creazione iniziale del progetto
- Avviare VS.NET e selezionare l’opzione Fichier/Nouveau/Projet

- specificare le caratteristiche del progetto
![]() |
- selezionare il tipo di progetto che si desidera realizzare, in questo caso un progetto VB.NET (1)
- selezionare il tipo di applicazione che si desidera creare, in questo caso un'applicazione Windows (2)
- indica in quale cartella desideri collocare la sottocartella del progetto (3)
- Indica il nome del progetto (4). Questo sarà anche il nome della cartella che conterrà i file del progetto
- il nome di questa cartella viene riportato al punto (5)
- Vengono quindi creati alcuni file e cartelle all’interno della cartella i4:
sottocartelle della cartella progetto1 ![]() |
Di questi file, solo uno è rilevante: il file form1.cs, che è il file sorgente associato al modulo creato da VS.NET. Ci torneremo più avanti.
5.2.2. Le finestre dell’interfaccia di VS.NET
L’interfaccia di VS.NET mostra ora alcuni elementi del nostro progetto i4:
Abbiamo una finestra di progettazione dell’interfaccia grafica:
![]() |
Selezionando i controlli dalla barra degli strumenti (toolbox 2) e trascinandoli sull’area della finestra (1), possiamo costruire un’interfaccia grafica. Se passiamo il mouse sulla “toolbox”, questa si ingrandisce e mostra una serie di controlli:

Per il momento non ne utilizziamo nessuno. Sempre nella schermata di VS.NET, troviamo la finestra dell’Esplora soluzioni “Explorer Solution”:

In un primo momento, useremo poco questa finestra. Essa mostra tutti i file che compongono il progetto. Solo uno di essi ci interessa: il file sorgente del nostro programma, in questo caso Form1.vb. Cliccando con il tasto destro su Form1.vb, si apre un menu che consente di accedere sia al codice sorgente della nostra interfaccia grafica (Visualizza codice) sia all’interfaccia grafica stessa (Progettore di viste):

È possibile accedere a queste due entità direttamente dalla finestra «Esplora soluzioni»:
![]() | ![]() |
Le finestre aperte si “accumulano” nella finestra principale di progettazione:

Qui Form1.vb[Design] indica la finestra di progettazione e Form1.vb la finestra del codice. È sufficiente cliccare su una delle schede per passare da una finestra all'altra. Un’altra finestra importante presente sullo schermo di VS.NET è la finestra delle proprietà:

Le proprietà visualizzate nella finestra sono quelle del controllo attualmente selezionato nella finestra di progettazione grafica. È possibile accedere alle diverse finestre del progetto tramite il menu Affichage:

Qui si trovano le finestre principali appena descritte e le relative scorciatoie da tastiera.
5.2.3. Esecuzione di un progetto
Pur non avendo scritto alcun codice, disponiamo già di un progetto eseguibile. Eseguire F5 o Déboguer/Démarrer per avviarlo. Si otterrà la seguente finestra:

Questa finestra può essere ingrandita, ridotta a icona, ridimensionata e chiusa.
5.2.4. Il codice generato da VS.NET
Diamo un'occhiata al codice (Affichage/Code) della nostra applicazione:
Public Class Form1
Inherits System.Windows.Forms.Form
#Sezione "Codice generato dal Windows Form Designer"
Public Sub New()
MyBase.New()
'Questa chiamata è richiesta dal Windows Form Designer.
InitializeComponent()
'Aggiungere un'inizializzazione qualsiasi dopo la chiamata a InitializeComponent()
End Sub
'Il metodo sovrascritto Dispose del modulo per ripulire l'elenco dei componenti.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Richiesto dal Windows Form Designer
Private components As System.ComponentModel.IContainer
'REMARQUE: la procedura seguente è richiesta dal Designer di Windows Form
'Può essere modificata utilizzando il Designer di Windows Form.
'Non modificarla utilizzando l'editor di codice.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "Form2"
End Sub
#Fine regione
End Class
Un'interfaccia grafica deriva dalla classe base System.Windows.Forms.Form:
La classe base Form definisce una finestra di base con pulsanti di chiusura, ingrandimento/riduzione, dimensioni regolabili, ... e gestisce gli eventi su questi oggetti grafici. Il costruttore del modulo utilizza un metodo InitializeComponent in cui vengono creati e inizializzati i controlli del modulo.
Public Sub New()
MyBase.New()
'Questa chiamata è richiesta dal Windows Form Designer.
InitializeComponent()
'Aggiungere un'inizializzazione qualsiasi dopo la chiamata a InitializeComponent()
End Sub
Qualsiasi altra operazione da eseguire nel generatore può essere effettuata dopo la chiamata a InitializeComponent. Il metodo InitializeComponent
Private Sub InitializeComponent()
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 53)
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
imposta il titolo della finestra "Form1", la sua larghezza (292) e la sua altezza (53). Il titolo della finestra è definito dalla proprietà Text e le dimensioni dalla proprietà Size. Size è definito nello spazio dei nomi System.Drawing ed è una struttura. Per eseguire questa applicazione, è necessario definire il modulo principale del progetto. A tal fine, si utilizza l'opzione [Projets/Propriétés]:

In [Objet de démarrage], indichiamo [Form1], ovvero il modulo che abbiamo appena creato. Per avviare l'esecuzione, utilizziamo l'opzione [Déboguer/Démarrer]:

5.2.5. Compilazione in una finestra DOS
Ora proviamo a compilare ed eseguire questa applicazione in una finestra DOS:
dos>dir form1.vb
14/03/2004 11:53 514 Form1.vb
dos>vbc /r:system.dll /r:system.windows.forms.dll form1.vb
vbc : error BC30420: 'Sub Main' est introuvable dans 'Form1'.
Il compilatore segnala che non riesce a trovare la procedura [Main]. Infatti, VS.NET non l'ha generata. Tuttavia, l'abbiamo già incontrata negli esempi precedenti. Ha la seguente forma:
Shared Sub Main()
' si avvia l'applicazione
Application.Run(New Form1) ' où Form1 est le formulaire
End Sub
Aggiungiamo nel codice di [Form1.vb] il codice precedente e ricompiliamo:
dos>vbc /r:system.dll /r:system.windows.forms.dll form2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
Form2.vb(41) : error BC30451: Le nom 'Application' n'est pas déclaré.
Application.Run(New Form2)
~~~~~~~~~~~
In questo caso, il nome [Application] non è riconosciuto. Ciò significa semplicemente che non abbiamo importato il suo spazio dei nomi [System.Windows.Forms]. Aggiungiamo la seguente istruzione:
quindi ricompiliamo:
Questa volta funziona. Eseguiamo:

Viene creato e visualizzato un modulo di tipo Form1. È possibile evitare l'aggiunta della procedura [Main] utilizzando l'opzione /m del compilatore, che consente di specificare la classe da eseguire nel caso in cui questa erediti da System.Windows.Form:
L'opzione /m:form2 indica che la classe da eseguire è quella denominata [form2].
5.2.6. Gestione degli eventi
Una volta visualizzato il modulo, l’applicazione si mette in ascolto degli eventi che si verificano sul modulo (clic, spostamenti del mouse, ecc.) e fa eseguire quelli gestiti dal modulo stesso. In questo caso, il nostro modulo non gestisce altri eventi oltre a quelli gestiti dalla classe di base Form (clic sui pulsanti di chiusura, ingrandimento/riduzione, modifica delle dimensioni della finestra, spostamento della finestra, ecc.). Il modulo generato utilizza un attributo components che non viene utilizzato da nessuna parte. Anche il metodo dispose non serve a nulla in questo contesto. Lo stesso vale per alcuni spazi dei nomi (Collections, ComponentModel, Data) utilizzati e per quello definito per il progetto projet1. Pertanto, in questo esempio il codice può essere semplificato come segue:
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
' costruttore
Public Sub New()
' creazione del modulo con i relativi componenti
InitializeComponent()
End Sub
Private Sub InitializeComponent()
' dimensioni della finestra
Me.Size = New System.Drawing.Size(300, 300)
' titolo della finestra
Me.Text = "Form1"
End Sub
Shared Sub Main()
' si avvia l'app
Application.Run(New Form1)
End Sub
End Class
5.2.7. Conclusione
Ora accetteremo così com'è il codice generato da VS.NET e ci limiteremo ad aggiungere il nostro, in particolare per gestire gli eventi relativi ai vari controlli del modulo.
5.3. Finestra con campo di immissione, pulsante ed etichetta
5.3.1. Progettazione grafica
Nell’esempio precedente non avevamo inserito alcun componente nella finestra. Iniziamo un nuovo progetto denominato interface2. A tal fine seguiamo la procedura illustrata in precedenza per creare un progetto:

Ora creiamo una finestra con un pulsante, un'etichetta e un campo di immissione:
![]() |
I campi sono i seguenti:
n° | nome | tipo | ruolo |
1 | lblSaisie | Etichetta | una dicitura |
2 | txtSaisie | TextBox | un campo di immissione |
3 | btnAfficher | Pulsante | per visualizzare in una finestra di dialogo il contenuto del campo di immissione txtSaisie |
Per creare questa finestra, procedere come segue: fare clic con il tasto destro del mouse all'interno della finestra, al di fuori di qualsiasi componente, e selezionare l'opzione Properties per accedere alle proprietà della finestra:

La finestra delle proprietà apparirà quindi sulla destra:

È opportuno prendere nota di alcune di queste proprietà:
per impostare il colore di sfondo della finestra | |
per impostare il colore delle immagini o del testo nella finestra | |
per associare un menu alla finestra | |
per assegnare un titolo alla finestra | |
per impostare il tipo di finestra | |
per impostare il carattere dei testi nella finestra | |
per impostare il nome della finestra |
Qui impostiamo le proprietà Text e Name:
Campi di immissione e pulsanti - 1 | |
frmSaisiesBoutons |
Utilizzando la barra "Casella degli strumenti"
- selezionate i componenti di cui avete bisogno
- trascinateli nella finestra e impostate le dimensioni corrette
![]() | ![]() |
Una volta scelto il componente nella "toolbox", utilizzate il tasto "Esc" per far scomparire la barra degli strumenti, quindi trascinate e ridimensionate il componente. Ripetete l’operazione per i tre componenti necessari: Label, TextBox, Button. Per allineare e ridimensionare correttamente i componenti, utilizzate il menu Format: | ![]() |
Il principio di formattazione è il seguente:
L'opzione Align consente di allineare i componenti | ![]() |
L'opzione Make Same Size consente di fare in modo che componenti abbiano la stessa altezza o la stessa larghezza: | ![]() |
L'opzione "Horizontal Spacing" consente, ad esempio, di allineare orizzontalmente i componenti con intervalli di uguale dimensione tra di essi. Lo stesso vale per l'opzione "Vertical Spacing" per l'allineamento verticale. L'opzione "Center in Form" consente di centrare un componente in orizzontale o verticalmente nella finestra: | ![]() |
Una volta che i componenti sono stati posizionati correttamente posizionati nella finestra, impostate le loro proprietà. A tal fine, fare clic con il tasto destro del mouse sul componente e selezionare l'opzione Properties:
Selezionate il componente per visualizzarne la finestra delle proprietà. In essa, modificare le seguenti proprietà: nome: lblSaisie, testo: Inserimento
Selezionare il componente per visualizzarne la finestra delle proprietà. In essa, modificare le seguenti proprietà: nome: txtSaisie, testo: lasciare vuoto
name: cmdAfficher, text: Visualizza
text: Inserimenti e pulsanti - 1 | ![]() |
Possiamo eseguire (Ctrl+F5) il nostro progetto per avere una prima anteprima della finestra in azione: | ![]() |
Chiudete la finestra. Ora dobbiamo scrivere la procedura associata al clic sul pulsante Afficher.
5.3.2. Gestione degli eventi di un modulo
Diamo un'occhiata al codice generato dal designer grafico:
...
Public Class frmSaisiesBoutons
Inherits System.Windows.Forms.Form
' componenti
Private components As System.ComponentModel.Container = Nothing
Friend WithEvents btnAfficher As System.Windows.Forms.Button
Friend WithEvents lblsaisie As System.Windows.Forms.Label
Friend WithEvents txtsaisie As System.Windows.Forms.TextBox
' costruttore
Public Sub New()
InitializeComponent()
End Sub
...
' inizializzazione dei componenti
Private Sub InitializeComponent()
...
End Sub
End Class
Si noti innanzitutto la particolare dichiarazione dei componenti:
- la parola chiave Friend indica che la visibilità del componente si estende a tutte le classi del progetto
- la parola chiave WithEvents indica che il componente genera eventi. Passiamo ora a vedere come gestire questi eventi
Visualizzate la finestra del codice del modulo (Visualizza/Codice o F7):
![]() |
La finestra sopra riportata presenta due elenchi a discesa (1) e (2). L’elenco (1) è l’elenco dei componenti del modulo:

L'elenco (2) contiene gli eventi associati al componente selezionato in (1):

Uno degli eventi associati al componente è visualizzato in grassetto (in questo caso Click). Si tratta dell'evento predefinito del componente. È possibile accedere al gestore di questo specifico evento facendo doppio clic sul componente nella finestra di progettazione. VB.net genera quindi automaticamente lo scheletro del gestore dell’evento nella finestra di codice e posiziona l’utente su di esso. L'accesso ai gestori degli altri eventi avviene invece nella finestra del codice, selezionando il componente dall'elenco (1) e l'evento in (2). VB.net genera quindi lo scheletro del gestore dell'evento o si posiziona su di esso se era già stato generato:
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
Per impostazione predefinita, VB.net C_E assegna il nome “E” al gestore dell’evento del componente C. È possibile modificare questo nome se lo si ritiene opportuno. Tuttavia, tale operazione è sconsigliata. Gli sviluppatori di VB mantengono in genere il nome generato da VB, garantendo così la coerenza nella denominazione in tutti i programmi VB. L'associazione della procedura btnAfficher_Click all'evento Click del componente btnAfficher non avviene tramite il nome della procedura, ma tramite la parola chiave handles:
Handles btnAfficher.Click
Nell’esempio sopra riportato, la parola chiave «handles» specifica che la procedura gestisce l’evento «Click» del componente btnAfficher. Il gestore di eventi precedente ha due parametri:
l’oggetto all’origine dell’evento (in questo caso il pulsante) | |
un oggetto EventArgs che descrive in dettaglio l'evento verificatosi |
In questo caso non utilizzeremo nessuno di questi parametri. Non ci resta che completare il codice. In questo caso, vogliamo visualizzare una finestra di dialogo contenente il contenuto del campo txtSaisie:
Private Sub btnAfficher_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' viene visualizzato il testo inserito nella casella di immissione TxtSaisie
MessageBox.Show("texte saisi= " + txtsaisie.Text, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Se si esegue l’applicazione, si ottiene quanto segue:

5.3.3. Un altro metodo per gestire gli eventi
Per il pulsante btnAfficher, VS.NET ha generato il codice seguente:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
...
End Sub
...
' gestione evento clic sul pulsante cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
Possiamo associare la procedura btnAfficher_Click all’evento Click del pulsante btnAfficher in un altro modo:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
...
End Sub
...
' gestore di eventi clic sul pulsante cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
...
End Sub
La procedura btnAfficher_Click ha perso la parola chiave Handles, perdendo così il suo collegamento con l'evento btnAfficher.Click. Questo collegamento viene ora effettuato utilizzando la parola chiave AddHandler:
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
Il codice sopra riportato, che verrà inserito nella procedura InitializeComponent del modulo, associa all’evento btnAfficher.Click la procedura denominata btnAfficher_Click. Inoltre, il componente btnAfficher non necessita più della parola chiave WithEvents:
Friend btnAfficher As System.Windows.Forms.Button
Qual è la differenza tra i due metodi?
- La parola chiave «handles» consente di associare un evento a una procedura solo in fase di progettazione. Il progettista sa in anticipo che una procedura P deve gestire gli eventi E1, E2, ... e scrive il codice
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) handles E1, E2, ..., En
È infatti possibile che una procedura gestisca più eventi.
- La parola chiave addhandler consente di associare un evento a una procedura al momento dell’esecuzione. Ciò è utile in un contesto di produzione e consumo di eventi. Un oggetto genera un evento specifico che potrebbe interessare altri oggetti. Questi ultimi si iscrivono presso il produttore per ricevere l’evento (ad esempio, una temperatura che ha superato una soglia critica). Durante l’esecuzione dell’applicazione, il produttore dell’evento dovrà eseguire diverse istruzioni:
dove E è l’evento generato dal produttore e Pi le procedure appartenenti ai diversi oggetti consumatori di tale evento. Avremo modo di tornare su un’applicazione produttore-consumatore di eventi in un prossimo capitolo.
5.3.4. Conclusione
Dai due progetti esaminati, possiamo concludere che, una volta realizzata l’interfaccia grafica con VS.NET, il compito dello sviluppatore consiste nello scrivere i gestori degli eventi che desidera gestire per tale interfaccia grafica. D’ora in poi presenteremo solo il codice di questi ultimi.
5.4. Alcuni componenti utili
Presentiamo ora diverse applicazioni che utilizzano i componenti più comuni, al fine di illustrarne i principali metodi e proprietà. Per ciascuna applicazione, presentiamo l’interfaccia grafica e il codice rilevante, in particolare i gestori di eventi.
5.4.1. Modulo Form
Iniziamo presentando il componente indispensabile, il modulo su cui vengono inseriti i componenti. Abbiamo già illustrato alcune delle sue proprietà di base. Ci soffermeremo qui su alcuni eventi importanti di un modulo.
il modulo è in fase di caricamento | |
il modulo si sta chiudendo | |
il modulo è chiuso |
L'evento Load si verifica prima ancora che il modulo venga visualizzato. L'evento Closing si verifica quando il modulo sta per essere chiuso. È comunque possibile interrompere questa chiusura tramite programmazione. Creiamo un modulo denominato Form1 senza componenti:

Gestiamo i tre eventi precedenti:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' caricamento iniziale del modulo
MessageBox.Show("Evt Load", "Load")
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
' il modulo si sta chiudendo
MessageBox.Show("Evt Closing", "Closing")
' viene richiesta la conferma
Dim réponse As DialogResult = MessageBox.Show("Voulez-vous vraiment quitter l'application", "Closing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If réponse = DialogResult.No Then
e.Cancel = True
End If
End Sub
Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
' il modulo si sta chiudendo
MessageBox.Show("Evt Closed", "Closed")
End Sub
Utilizziamo la funzione MessageBox per ricevere una notifica dei diversi eventi. L'evento Closing si verificherà quando l'utente chiude la finestra. | ![]() |
A quel punto gli chiediamo se desidera davvero uscire dall’applicazione: | ![]() |
Se risponde No, impostiamo la proprietà Cancel dell’evento CancelEventArgs che il metodo ha ricevuto come parametro. Se impostiamo questa proprietà su False, la chiusura della finestra viene annullata, altrimenti procede: | ![]() |
5.4.2. etichette Label e caselle di immissione TextBox
Abbiamo già incontrato questi due componenti. Label è un componente di testo e TextBox un componente campo di immissione. La loro proprietà principale è Text, che indica il contenuto del campo di immissione o il testo dell’etichetta. Questa proprietà è di tipo lettura/scrittura. L’evento solitamente utilizzato per TextBox è TextChanged, che segnala che l’utente ha modificato il campo di immissione. Ecco un esempio che utilizza l’evento TextChanged per monitorare le modifiche apportate a un campo di immissione:
![]() |
n. | tipo | nome | ruolo |
1 | TextBox | txtSaisie | campo di immissione |
2 | Etichetta | lblControle | visualizza il testo di 1 in tempo reale |
3 | Pulsante | cmdEffacer | per cancellare i campi 1 e 2 |
4 | Pulsante | cmdQuitter | per uscire dall'applicazione |
Il codice rilevante di questa applicazione è quello dei gestori di eventi:
' clic sul pulsante Esci
Private Sub cmdQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdQuitter.Click
' clic sul pulsante "Esci" - si esce dall'applicazione
Application.Exit()
End Sub
' modifica del campo txtSaisie
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' il contenuto di TextBox è cambiato - lo si copia nell'etichetta lblControle
lblControle.Text = txtSaisie.Text
End Sub
' clic sul pulsante "Cancella"
Private Sub cmdEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdEffacer.Click
' si cancella il contenuto della casella di immissione
txtSaisie.Text = ""
End Sub
' è stato premuto un tasto
Private Sub txtSaisie_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles txtSaisie.KeyPress
' si verifica quale tasto è stato premuto
Dim touche As Char = e.KeyChar
If touche = ControlChars.Cr Then
MessageBox.Show(txtSaisie.Text, "Contrôle", MessageBoxButtons.OK, MessageBoxIcon.Information)
e.Handled = True
End If
End Sub
Si noti il modo in cui l'applicazione viene chiusa nella procedura cmdQuitter_Click: Application.Exit(). L'esempio seguente utilizza un TextBox su più righe:
![]() |
L'elenco dei controlli è il seguente:
n. | tipo | nome | ruolo |
1 | TextBox | txtMultiLignes | campo di immissione multilinea |
2 | TextBox | txtAjout | campo di immissione a riga singola |
3 | Pulsante | btnAjouter | Aggiunge il contenuto da 2 a 1 |
Affinché un TextBox diventi multilinea, è necessario impostare le seguenti proprietà del controllo:
per accettare più righe di testo | |
per specificare se il controllo deve avere o meno le barre di scorrimento (Horizontal, Vertical, Both) o nessuna (None) | |
se impostato su true, il tasto Invio inserirà un'interruzione di riga | |
se impostato su true, il tasto Tab inserirà un tabulatore nel testo |
Il codice utile è quello che gestisce il clic sul pulsante [Ajouter] e quello che gestisce la modifica del campo di immissione [txtAjout]:
' eventualmente btnAjouter_Click
Private Sub btnAjouter_Click1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' aggiunta del contenuto di txtAjout a quello di txtMultilignes
txtMultilignes.Text &= txtAjout.Text
txtAjout.Text = ""
End Sub
' eventualmente txtAjout_TextChanged
Private Sub txtAjout_TextChanged1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtAjout.TextChanged
' si imposta lo stato del pulsante Aggiungi
btnAjouter.Enabled = txtAjout.Text.Trim() <> ""
End Sub
5.4.3. elenchi a discesa ComboBox
![]() | ![]() |
Un componente ComboBox è un elenco a discesa abbinato a un campo di immissione: l'utente può scegliere un elemento in (2) oppure digitare del testo in (1). Esistono tre tipi di ComboBox definiti dalla proprietà Style:
elenco non a tendina con campo di modifica | |
elenco a discesa con campo di modifica | |
elenco a discesa senza campo di modifica |
Per impostazione predefinita, il tipo di un ComboBox è DropDown. Per scoprire la classe ComboBox, digitare ComboBox nell'indice della guida (Aide/Index). La classe ComboBox ha un unico costruttore:
Public Sub New() | crea un oggetto ComboBox vuoto |
Gli elementi di ComboBox sono disponibili nella proprietà Items:
Si tratta di una proprietà indicizzata, dove Items(i) indica l'elemento i del Combo. Supponiamo che C sia un Combo e C.Items il suo elenco di elementi. Abbiamo le seguenti proprietà:
numero di elementi del menu a discesa | |
elemento i del menu a discesa | |
aggiunge l'oggetto o come ultimo elemento del menu a tendina | |
aggiunge un array di oggetti alla fine del menu a tendina | |
aggiunge l'oggetto o nella posizione i del menu a tendina | |
rimuove l'elemento i dal menu a tendina | |
rimuove l'oggetto o dal menu a tendina | |
elimina tutti gli elementi dal menu a tendina | |
restituisce la posizione i dell'oggetto o nel menu a discesa |
Potrebbe sorprendere che un menu a tendina possa contenere oggetti, mentre solitamente contiene stringhe di caratteri. Dal punto di vista visivo, è proprio così. Se un ComboBox contiene un oggetto obj, visualizza la stringa obj.ToString(). Ricordiamo che ogni oggetto dispone di un metodo ToString ereditato dalla classe object, che restituisce una stringa di caratteri «rappresentativa» dell’oggetto. L'elemento selezionato nel menu a tendina C è C.SelectedItem oppure C.Items(C.SelectedIndex), dove C.SelectedIndex è il numero dell'elemento selezionato, numero che parte da zero per il primo elemento.
Quando si seleziona un elemento dall’elenco a discesa, si verifica l’evento SelectedIndexChanged, che può quindi essere utilizzato per ricevere una notifica del cambiamento di selezione nel menu a discesa. Nell’applicazione seguente, utilizziamo questo evento per visualizzare l’elemento che è stato selezionato nell’elenco.

Presentiamo solo il codice rilevante della finestra. Nel costruttore del modulo popoliamo il menu a discesa:
Public Sub New()
' creazione del modulo
InitializeComponent()
' compilazione del menu a tendina
cmbNombres.Items.AddRange(New String() {"zéro", "un", "deux", "trois", "quatre"})
' si seleziona il primo elemento dell'elenco
cmbNombres.SelectedIndex = 0
End Sub
Gestiamo l’evento SelectedIndexChanged del menu a tendina che segnala un nuovo elemento selezionato:
Private Sub cmbNombres_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmbNombres.SelectedIndexChanged
' l'elemento selezionato è cambiato - lo visualizziamo
MessageBox.Show("Elément sélectionné : (" & cmbNombres.SelectedItem.ToString & "," & cmbNombres.SelectedIndex & ")", "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
5.4.4. componente ListBox
Ci proponiamo di realizzare la seguente interfaccia:
![]() |
I componenti di questa finestra sono i seguenti:
n. | tipo | nome | ruolo/proprietà |
0 | Form | Form1 | modulo - BorderStyle=FixedSingle |
1 | TextBox | txtSaisie | campo di inserimento |
2 | Pulsante | btnAjouter | pulsante che consente di aggiungere il contenuto del campo di immissione 1 all'elenco 3 |
3 | ListBox | listBox1 | elenco 1 |
4 | ListBox | listBox2 | elenco 2 |
5 | Pulsante | btn1TO2 | sposta gli elementi selezionati dall'elenco 1 all'elenco 2 |
6 | Pulsante | cmd2T0 | esegue l'operazione inversa |
7 | Pulsante | btnEffacer1 | svuota l'elenco 1 |
8 | Pulsante | btnEffacer2 | svuota l'elenco 2 |
- L'utente digita del testo nel campo 1. Lo aggiunge all'elenco 1 tramite il pulsante Ajouter (2). Il campo di immissione (1) viene quindi svuotato e l'utente può aggiungere un nuovo elemento.
- Può trasferire elementi da un elenco all’altro selezionando l’elemento da trasferire in uno degli elenchi e scegliendo il pulsante di trasferimento appropriato 5 o 6. L’elemento trasferito viene aggiunto alla fine dell’elenco di destinazione e rimosso dall’elenco di origine.
- Può fare doppio clic su un elemento dell’elenco 1. L’elemento viene quindi trasferito nella casella di immissione per essere modificato e rimosso dall’elenco 1.
I pulsanti sono attivi o disattivi secondo le seguenti regole:
- il pulsante Ajouter è attivo solo se nel campo di immissione è presente del testo
- il pulsante 5 di trasferimento dall’elenco 1 all’elenco 2 è attivo solo se nell’elenco 1 è presente un elemento selezionato
- il pulsante 6 per il trasferimento dall’elenco 2 all’elenco 1 è attivo solo se nell’elenco 2 è presente un elemento selezionato
- i pulsanti 7 e 8 per la cancellazione delle liste 1 e 2 sono attivi solo se la lista da cancellare contiene elementi.
Nelle condizioni precedenti, tutti i pulsanti devono essere spenti all’avvio dell’applicazione. È quindi necessario impostare la proprietà Enabled dei pulsanti su false. È possibile farlo in fase di progettazione, il che genererà il codice corrispondente nel metodo InitializeComponent, oppure farlo manualmente nel costruttore come di seguito:
Public Sub New()
' creazione iniziale del modulo
InitializeComponent()
' inizializzazioni aggiuntive
' si disabilitano alcuni pulsanti
btnAjouter.Enabled = False
btn1TO2.Enabled = False
btn2TO1.Enabled = False
btnEffacer1.Enabled = False
btnEffacer2.Enabled = False
End Sub
Lo stato del pulsante Ajouter è controllato dal contenuto del campo di immissione. È l’evento TextChanged che ci permette di monitorare le modifiche di tale contenuto:
' modifica nel campo di immissione testo
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' il contenuto di txtSaisie è cambiato
' il pulsante Aggiungi è attivo solo se il campo di immissione non è vuoto
btnAjouter.Enabled = txtSaisie.Text.Trim() <> ""
End Sub
Lo stato dei pulsanti di trasferimento dipende dal fatto che sia stato selezionato o meno un elemento nell'elenco che essi controllano:
' modifica dell'elemento selezionato senza listbox1
Private Sub listBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox1.SelectedIndexChanged
' è stato selezionato un elemento
' si attiva il pulsante di trasferimento da 1 a 2
btn1TO2.Enabled = True
End Sub
' modifica dell'elemento selezionato senza listbox2
Private Sub listBox2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox2.SelectedIndexChanged
' È stato selezionato un elemento
' si attiva il pulsante di trasferimento da 2 a 1
btn2TO1.Enabled = True
End Sub
Il codice associato al clic sul pulsante Ajouter è il seguente:
' clic sul pulsante Aggiungi
Private Sub btnAjouter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' aggiunta di un nuovo elemento all'elenco 1
listBox1.Items.Add(txtSaisie.Text.Trim())
' cancellazione del dato inserito
txtSaisie.Text = ""
' L'elenco 1 non è vuoto
btnEffacer1.Enabled = True
' il focus torna sulla casella di immissione
txtSaisie.Focus()
End Sub
Da notare il metodo Focus che consente di portare il «focus» su un controllo del modulo. Il codice associato al clic sui pulsanti Effacer:
' clic sul pulsante Cancella1
Private Sub btnEffacer1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer1.Click
' si cancella la lista 1
listBox1.Items.Clear()
btnEffacer1.Enabled = False
End Sub
' clic sul pulsante Cancella2
Private Sub btnEffacer2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' si cancella l'elenco 2
listBox2.Items.Clear()
btnEffacer2.Enabled = False
End Sub
Il codice per trasferire gli elementi selezionati da un elenco all’altro:
' clic sul pulsante btn1to2
Private Sub btn1TO2_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn1TO2.Click
' trasferimento dell'elemento selezionato dall'Elenco 1 all'Elenco 2
transfert(listBox1, listBox2)
' Pulsanti «Cancella»
btnEffacer2.Enabled = True
btnEffacer1.Enabled = listBox1.Items.Count <> 0
' Pulsanti di trasferimento
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' clic sul pulsante btn2to1
Private Sub btn2TO1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn2TO1.Click
' trasferimento dell'elemento selezionato dall'Elenco 2 all'Elenco 1
transfert(listBox2, listBox1)
' pulsanti Cancella
btnEffacer1.Enabled = True
btnEffacer2.Enabled = listBox2.Items.Count <> 0
' pulsanti di trasferimento
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' trasferimento
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
' trasferimento dell'elemento selezionato dall'elenco 1 all'elenco l2
' un elemento selezionato?
If l1.SelectedIndex = -1 Then Return
' aggiunta in l2
l2.Items.Add(l1.SelectedItem)
' eliminazione da l1
l1.Items.RemoveAt(l1.SelectedIndex)
End Sub
Per prima cosa, si crea un metodo
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
che trasferisce nell'elenco l2 l'elemento selezionato nell'elenco l1. Questo ci permette di avere un unico metodo invece di due per trasferire un elemento da listBox1 a listBox2 o da listBox2 a listBox1. Prima di effettuare il trasferimento, ci assicuriamo che sia effettivamente selezionato un elemento nell’elenco l1:
' un elemento selezionato?
If l1.SelectedIndex = -1 Then Return
La proprietà SelectedIndex assume il valore -1 se al momento non è selezionato alcun elemento. Nelle procedure
Private Sub btnXTOY_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnXTOY.Click
si esegue il trasferimento dall'elenco X all'elenco Y e si modifica lo stato di alcuni pulsanti per riflettere il nuovo stato degli elenchi.
5.4.5. caselle di controllo CheckBox, pulsanti di opzione ButtonRadio
Ci proponiamo di scrivere la seguente applicazione:
![]() |
I componenti della finestra sono i seguenti:
n° | tipo | nome | ruolo |
1 | RadioButton | radioButton1 radioButton2 radioButton3 | 3 pulsanti di opzione |
2 | CheckBox | chechBox1 chechBox2 chechBox3 | 3 caselle di selezione |
3 | ListBox | lstValeurs | un elenco |
Se si creano i tre pulsanti di opzione uno dopo l'altro, per impostazione predefinita fanno parte dello stesso gruppo. Pertanto, quando uno è selezionato, gli altri non lo sono. L'evento che ci interessa per questi sei controlli è l'evento CheckChanged, che indica che lo stato della casella di controllo o del pulsante di opzione è cambiato. Questo stato è rappresentato in entrambi i casi dalla proprietà booleana Check che, se vera, significa che il controllo è selezionato. In questo caso abbiamo utilizzato un unico metodo per gestire i sei eventi CheckChanged, ovvero il metodo affiche:
' visualizza
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles checkBox1.CheckedChanged, checkBox2.CheckedChanged, checkBox3.CheckedChanged, _
radioButton1.CheckedChanged, radioButton2.CheckedChanged, radioButton3.CheckedChanged
' visualizza lo stato del pulsante di opzione o della casella di controllo
' è una casella di controllo?
If (TypeOf (sender) Is CheckBox) Then
Dim chk As CheckBox = CType(sender, CheckBox)
lstValeurs.Items.Insert(0, chk.Name & "=" & chk.Checked)
End If
' È un pulsante di opzione?
If (TypeOf (sender) Is RadioButton) Then
Dim rdb As RadioButton = CType(sender, RadioButton)
lstValeurs.Items.Insert(0, rdb.Name & "=" & rdb.Checked)
End If
End Sub
La sintassi TypeOf (mittente) Is CheckBox consente di verificare se l’oggetto sender è di tipo CheckBox. Ciò ci permette quindi di effettuare una conversione al tipo esatto di sender. Il metodo affiche scrive nell’elenco lstValeurs il nome del componente all’origine dell’evento e il valore della sua proprietà Checked. All'esecuzione, si osserva che un clic su un pulsante di opzione provoca due eventi CheckChanged: uno sul vecchio pulsante selezionato, che passa a “non selezionato”, e l’altro sul nuovo pulsante, che passa a “selezionato”.
5.4.6. regolatori ScrollBar
Esistono diversi tipi di variatore: il variatore orizzontale (hScrollBar), il variatore verticale (vScrollBar), l’incrementatore (NumericUpDown). | ![]() |
Realizziamo la seguente applicazione:
![]() |
n. | tipo | nome | ruolo |
1 | hScrollBar | hScrollBar1 | un variatore orizzontale |
2 | hScrollBar | hScrollBar2 | un variatore orizzontale che segue le variazioni del variatore 1 |
3 | TextBox | txtValeur | visualizza il valore del variatore orizzontale ReadOnly=true per impedire qualsiasi immissione |
4 | NumericUpDown | incrementatore | consente di impostare il valore del variatore 2 |
- Un variatore ScrollBar consente all'utente di scegliere un valore all'interno di un intervallo di valori interi rappresentato dalla "barra" del variatore su cui si sposta un cursore. Il valore del variatore è disponibile nella sua proprietà Value.
- Per un variatore orizzontale, l’estremità sinistra rappresenta il valore minimo dell’intervallo, l’estremità destra il valore massimo, mentre il cursore rappresenta il valore attuale selezionato. Per un variatore verticale, il minimo è rappresentato dall’estremità superiore, il massimo dall’estremità inferiore. Questi valori sono rappresentati dalle proprietà Minimum e Maximum e hanno valori predefiniti pari a 0 e 100.
- Un clic sulle estremità del variatore modifica il valore di un incremento (positivo o negativo) a seconda dell’estremità cliccata, denominata SmallChange, il cui valore predefinito è 1.
- Un clic su entrambi i lati del cursore fa variare il valore di un incremento (positivo o negativo) a seconda dell’estremità cliccata, denominata LargeChange, che per impostazione predefinita è 10.
- Quando si clicca sull’estremità superiore di un cursore verticale, il suo valore diminuisce. Ciò può sorprendere l’utente medio, che normalmente si aspetta di vedere il valore «aumentare». Si risolve questo problema assegnando un valore negativo alle proprietà SmallChange e LargeChange
- Queste cinque proprietà (Value, Minimum, Maximum, SmallChange, LargeChange) sono accessibili sia in lettura che in scrittura.
- L'evento principale del variatore è quello che segnala una variazione di valore: l'evento Scroll.
Un componente NumericUpDown si trova vicino al variatore: anch’esso presenta le proprietà Minimum, Maximum e Value, con valori predefiniti rispettivamente pari a 0, 100 e 0. In questo caso, però, la proprietà Value viene visualizzata in una casella di immissione che fa parte integrante del controllo. L'utente può modificare autonomamente questo valore, a meno che non si sia impostata la proprietà ReadOnly del controllo su "vero". Il valore dell'incremento è definito dalla proprietà Increment, il cui valore predefinito è 1. L'evento principale del componente NumericUpDown è quello che segnala una modifica del valore: l'evento ValueChanged. Il codice utile della nostra applicazione è il seguente:
Il modulo viene formattato al momento della sua creazione:
' costruttore
Public Sub New()
' creazione iniziale del modulo
InitializeComponent()
' si assegnano al variatore 2 le stesse caratteristiche del variatore 1
hScrollBar2.Minimum = hScrollBar1.Value
hScrollBar2.Minimum = hScrollBar1.Minimum
hScrollBar2.Maximum = hScrollBar1.Maximum
hScrollBar2.LargeChange = hScrollBar1.LargeChange
hScrollBar2.SmallChange = hScrollBar1.SmallChange
' idem per l'incrementatore
incrémenteur.Minimum = hScrollBar1.Value
incrémenteur.Minimum = hScrollBar1.Minimum
incrémenteur.Maximum = hScrollBar1.Maximum
incrémenteur.Increment = hScrollBar1.SmallChange
' si assegna a TextBox il valore del variatore 1
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Il gestore che monitora le variazioni di valore del variatore 1:
' gestione del variatore hscrollbar1
Private Sub hScrollBar1_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar1.Scroll
' modifica del valore del variatore 1
' si trasferisce il suo valore al variatore 2 e alla casella di testo TxtValeur
hScrollBar2.Value = hScrollBar1.Value
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Il gestore che monitora le variazioni di valore del variatore 2:
' gestione del variatore hscrollbar2
Private Sub hScrollBar2_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar2.Scroll
' si inibisce qualsiasi modifica del variatore 2
' costringendolo a mantenere il valore del variatore 1
e.NewValue = hScrollBar1.Value
End Sub
Il gestore che monitora le variazioni del controllo incrémenteur:
' gestione dell'incrementatore
Private Sub incrémenteur_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles incrémenteur.ValueChanged
' si imposta il valore del variatore 2
hScrollBar2.Value = CType(incrémenteur.Value, Integer)
End Sub
5.5. Eventi del mouse
Quando si disegna in un contenitore, è importante conoscere la posizione del mouse per, ad esempio, visualizzare un punto al clic. Gli spostamenti del mouse generano eventi nel contenitore in cui si muove.
![]() | ![]() |
il mouse è appena entrato nell’area del controllo | |
il mouse ha appena lasciato l'area di controllo | |
il mouse si sta muovendo nell'area di controllo | |
Pressione del tasto sinistro del mouse | |
Rilascio del tasto sinistro del mouse | |
l'utente rilascia un oggetto sul controllo | |
l'utente entra nell'area del controllo trascinando un oggetto | |
l'utente esce dall'area del controllo trascinando un oggetto | |
l'utente passa sopra l'area del controllo trascinando un oggetto |
Ecco un programma che permette di comprendere meglio in quali momenti si verificano i diversi eventi del mouse:
![]() |
n. | tipo | nome | ruolo |
1 | Etichetta | lblPosition | per visualizzare la posizione del mouse nel modulo 1, nell'elenco 2 o nel pulsante 3 |
2 | ListBox | lstEvts | per visualizzare gli eventi del mouse diversi da MouseMove |
3 | Pulsante | btnEffacer | per cancellare il contenuto di 2 |
I gestori di eventi sono i seguenti. Per seguire i movimenti del mouse sui tre controlli, si scrive un solo gestore:
' event. form1_mousemove
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseMove, lstEvts.MouseMove, btnEffacer.MouseMove, lstEvts.MouseMove
' movimento del mouse - visualizzazione delle coordinate (X,Y) del mouse
lblPosition.Text = "(" & e.X & "," & e.Y & ")"
End Sub
È importante sapere che ogni volta che il mouse entra nell'area di un controllo, il suo sistema di coordinate cambia. Il suo punto di origine (0,0) è l'angolo superiore sinistro del controllo su cui si trova. Pertanto, durante l'esecuzione, quando si sposta il mouse dal modulo al pulsante, si nota chiaramente il cambiamento delle coordinate. Per osservare meglio questi cambiamenti di area del mouse, è possibile utilizzare la proprietà Cursor dei controlli:

Questa proprietà consente di impostare la forma del cursore del mouse quando questo entra nell’area del controllo. Pertanto, nel nostro esempio, abbiamo impostato il cursore su Default per il modulo stesso, su Hand per l’elenco 2 e su No per il pulsante 3, come mostrano le schermate riportate di seguito.



Nel metodo [InitializeComponent], il codice generato da queste impostazioni è il seguente:
Me.lstEvts.Cursor = System.Windows.Forms.Cursors.Hand
Me.btnEffacer.Cursor = System.Windows.Forms.Cursors.No
Inoltre, per rilevare l'entrata e l'uscita del mouse dall'elenco 2, elaboriamo gli eventi MouseEnter e MouseLeave dello stesso elenco:
' evt lstEvts_MouseEnter
Private Sub lstEvts_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseEnter
affiche("MouseEnter sur liste")
End Sub
' evento lstEvts_MouseLeave
Private Sub lstEvts_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseLeave
affiche("MouseLeave sur liste")
End Sub
' visualizza
Private Sub affiche(ByVal message As String)
' il messaggio viene visualizzato in cima all'elenco degli eventi
lstEvts.Items.Insert(0, message)
End Sub

Per gestire i clic sul modulo, elaboriamo gli eventi MouseDown e MouseUp:
' evento Form1_MouseDown
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseDown
affiche("MouseDown sur formulaire")
End Sub
' evento Form1_MouseUp
Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseUp
affiche("MouseUp sur formulaire")
End Sub

Infine, il codice del gestore del clic sul pulsante Effacer:
' evento btnEffacer_Click
Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' cancella l'elenco degli eventi
lstEvts.Items.Clear()
End Sub
5.6. Creare una finestra con menu
Vediamo ora come creare una finestra con menu. Creeremo la seguente finestra:
![]() |
Il controllo 1 è un TextBox in sola lettura (ReadOnly=true) e denominato txtStatut. La struttura ad albero del menu è la seguente:
![]() | ![]() |
Le opzioni di menu sono controlli come gli altri componenti visivi e dispongono di proprietà ed eventi. Ad esempio, la tabella delle proprietà dell’opzione di menu A1:

Nel nostro esempio vengono utilizzate due proprietà:
il nome del controllo menu | |
il testo dell'opzione di menu |
Le proprietà delle diverse opzioni di menu del nostro esempio sono le seguenti:
Nome | Testo |
mnuA | Opzioni A |
mnuA1 | A1 |
mnuA2 | A2 |
mnuA3 | A3 |
mnuB | opzioni B |
mnuB1 | B1 |
mnuSep1 | - (separatore) |
mnuB2 | B2 |
mnuB3 | B3 |
mnuB31 | B31 |
mnuB32 | B32 |
Per creare un menu, selezionare il componente "MainMenu" nella barra "ToolBox":

Si ottiene così un menu vuoto che viene inserito nel modulo con delle caselle vuote denominate "Type Here". È sufficiente inserire le diverse opzioni del menu:

Per inserire un separatore tra due opzioni, come sopra tra le opzioni B1 e B2, posizionarsi nel punto in cui si desidera inserire il separatore nel menu, fare clic con il tasto destro del mouse e selezionare l’opzione “Insert Separator”:

Se si avvia l’applicazione con Ctrl+F5, si ottiene un modulo con un menu che per il momento non svolge alcuna funzione. Le opzioni del menu sono trattate come componenti: dispongono di proprietà ed eventi. In [fenêtre de code], selezionare il componente mnuA1, quindi selezionare gli eventi associati:

Se sopra si genera l’evento Click, VS.NET genera automaticamente la seguente procedura:
Private Sub mnuA1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuA.Click
....
End Sub
Potremmo procedere in questo modo per tutte le opzioni di menu. In questo caso, la stessa procedura può essere utilizzata per tutte le opzioni. Pertanto, rinominiamo la procedura precedente affiche e dichiariamo gli eventi che gestisce:
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mnuA1.Click, mnuA2.Click, mnuB1.Click, mnuB2.Click, mnuB31.Click, mnuB32.Click
' visualizza in TextBox il nome del sottomenu selezionato
txtStatut.Text = (CType(sender, MenuItem)).Text
End Sub
In questo metodo, ci limitiamo a visualizzare la proprietà Text dell'opzione di menu nella fonte dell'evento. La fonte dell'evento sender è di tipo object. Le opzioni di menu sono invece di tipo MenuItem, pertanto in questo caso è necessario effettuare una conversione da object a MenuItem. Eseguite l’applicazione e selezionate l’opzione A1 per ottenere il seguente messaggio:

Il codice utile di questa applicazione, oltre a quello del metodo affiche, è quello relativo alla creazione del menu nel costruttore del modulo (InitializeComponent):
Private Sub InitializeComponent()
Me.mainMenu1 = New System.Windows.Forms.MainMenu
Me.mnuA = New System.Windows.Forms.MenuItem
Me.mnuA1 = New System.Windows.Forms.MenuItem
Me.mnuA2 = New System.Windows.Forms.MenuItem
Me.mnuA3 = New System.Windows.Forms.MenuItem
Me.mnuB = New System.Windows.Forms.MenuItem
Me.mnuB1 = New System.Windows.Forms.MenuItem
Me.mnuB2 = New System.Windows.Forms.MenuItem
Me.mnuB3 = New System.Windows.Forms.MenuItem
Me.mnuB31 = New System.Windows.Forms.MenuItem
Me.mnuB32 = New System.Windows.Forms.MenuItem
Me.txtStatut = New System.Windows.Forms.TextBox
Me.mnuSep1 = New System.Windows.Forms.MenuItem
Me.SuspendLayout()
'
' mainMenu1
'
Me.mainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA, Me.mnuB})
'
' mnuA
'
Me.mnuA.Index = 0
Me.mnuA.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA1, Me.mnuA2, Me.mnuA3})
Me.mnuA.Text = "Options A"
'
' mnuA1
'
Me.mnuA1.Index = 0
Me.mnuA1.Text = "A1"
'
' mnuA2
'
Me.mnuA2.Index = 1
Me.mnuA2.Text = "A2"
'
' mnuA3
'
Me.mnuA3.Index = 2
Me.mnuA3.Text = "A3"
'
' mnuB
'
Me.mnuB.Index = 1
Me.mnuB.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB1, Me.mnuSep1, Me.mnuB2, Me.mnuB3})
Me.mnuB.Text = "Options B"
'
' mnuB1
'
Me.mnuB1.Index = 0
Me.mnuB1.Text = "B1"
'
' mnuB2
'
Me.mnuB2.Index = 2
Me.mnuB2.Text = "B2"
'
' mnuB3
'
Me.mnuB3.Index = 3
Me.mnuB3.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB31, Me.mnuB32})
Me.mnuB3.Text = "B3"
'
' mnuB31
'
Me.mnuB31.Index = 0
Me.mnuB31.Text = "B31"
'
' mnuB32
'
Me.mnuB32.Index = 1
Me.mnuB32.Text = "B32"
'
' txtStatut
'
Me.txtStatut.Location = New System.Drawing.Point(8, 8)
Me.txtStatut.Name = "txtStatut"
Me.txtStatut.ReadOnly = True
Me.txtStatut.Size = New System.Drawing.Size(112, 20)
Me.txtStatut.TabIndex = 0
Me.txtStatut.Text = ""
'
' mnuSep1
'
Me.mnuSep1.Index = 1
Me.mnuSep1.Text = "-"
'
' Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(136, 42)
Me.Controls.Add(txtStatut)
Me.Menu = Me.mainMenu1
Me.Name = "Form1"
Me.Text = "Menus"
Me.ResumeLayout(False)
End Sub
Da notare l’istruzione che associa il menu al modulo:
Me.Menu = Me.mainMenu1
5.7. Componenti non visivi
Ci occupiamo ora di una serie di componenti non visivi: vengono utilizzati in fase di progettazione, ma non sono visibili durante l’esecuzione.
5.7.1. Finestre di dialogo OpenFileDialog e SaveFileDialog
Realizzeremo la seguente applicazione:
![]() |
I controlli sono i seguenti:
N. | tipo | nome | ruolo |
1 | TextBox multilinea | txtTexte | testo digitato dall'utente o caricato da un file |
2 | Pulsante | btnSauvegarder | consente di salvare il testo di 1 in un file di testo |
3 | Pulsante | btnCharger | consente di caricare il contenuto di un file di testo in 1 |
4 | Pulsante | btnEffacer | cancella il contenuto di 1 |
Vengono utilizzati due controlli non visivi:

Quando vengono trascinati dal "ToolBox" e rilasciati sul modulo, vengono posizionati in un'area separata nella parte inferiore del modulo. I componenti "Dialog" vengono trascinati dal "ToolBox":

Il codice del pulsante Effacer è semplice:
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' si cancella la casella di immissione
txtTexte.Text = ""
End Sub
La classe SaveFileDialog è definita come segue:

Deriva da diversi livelli di classe. Tra le numerose proprietà e metodi, ne ricorderemo i seguenti:
i tipi di file disponibili nell’elenco a discesa dei tipi di file nella finestra di dialogo | |
il numero del tipo di file proposto per impostazione predefinita nell'elenco sopra riportato. Inizia da 0. | |
la cartella inizialmente indicata per il salvataggio del file | |
il nome del file di salvataggio specificato dall'utente | |
metodo che visualizza la finestra di dialogo di salvataggio. Restituisce un risultato di tipo DialogResult. |
Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:
![]() |
elenco a discesa generato dalla proprietà Filter. Il tipo di file proposto per impostazione predefinita è determinato da FilterIndex | |
cartella corrente, impostata da InitialDirectory se questa proprietà è stata specificata | |
nome del file scelto o digitato direttamente dall’utente. Sarà disponibile nella proprietà FileName | |
pulsanti Salva/Annulla. Se viene utilizzato il pulsante Enregistrer, la funzione ShowDialog restituisce il risultato DialogResult.OK |
La procedura di salvataggio può essere scritta come segue:
Private Sub btnSauvegarder_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnSauvegarder.Click
' si salva la casella di immissione in un file di testo
' si configura la finestra di dialogo savefileDialog1
saveFileDialog1.InitialDirectory = Application.ExecutablePath
saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
saveFileDialog1.FilterIndex = 0
' si visualizza la finestra di dialogo e si recupera il risultato
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
' si recupera il nome del file
Dim nomFichier As String = saveFileDialog1.FileName
Dim fichier As StreamWriter = Nothing
Try
' si apre il file in modalità di scrittura
fichier = New StreamWriter(nomFichier)
' qui si inserisce il testo
fichier.Write(txtTexte.Text)
Catch ex As Exception
' problema
MessageBox.Show("Problème à l'écriture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' si chiude il file
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Si associa la cartella iniziale alla cartella che contiene l'eseguibile dell'applicazione:
- Si specificano i tipi di file da visualizzare
Si noti la sintassi dei filtri filtro1|filtro2|..|filtroi con filtroi= Testo|modello di file. In questo caso l'utente potrà scegliere tra i file *.txt e *.*.
- Si imposta il tipo di file da visualizzare all’inizio
In questo caso, saranno i file di tipo *.txt a essere visualizzati per primi all'utente.
- Viene visualizzata la finestra di dialogo e ne viene recuperato il risultato
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
- Mentre la finestra di dialogo è visualizzata, l'utente non ha più accesso al modulo principale (finestra di dialogo cosiddetta modale). L'utente specifica il nome del file da salvare e chiude la finestra di dialogo tramite il pulsante Salva, il pulsante Annulla oppure chiudendo direttamente la finestra. Il risultato del metodo ShowDialog è DialogResult.OK solo se l’utente ha utilizzato il pulsante Enregistrer per chiudere la finestra di dialogo.
- A questo punto, il nome del file da creare si trova ora nella proprietà FileName dell’oggetto saveFileDialog1. Si torna quindi alla creazione classica di un file di testo. Vi si scrive il contenuto di TextBox: txtTexte.Text, gestendo al contempo le eccezioni che potrebbero verificarsi.
La classe OpenFileDialog è molto simile alla classe SaveFileDialog e deriva dalla stessa linea di classi. Tra le sue proprietà e metodi, ne ricorderemo i seguenti:
i tipi di file proposti nell’elenco a discesa dei tipi di file della finestra di dialogo | |
il numero del tipo di file proposto per impostazione predefinita nell'elenco sopra riportato. Inizia da 0. | |
la cartella visualizzata inizialmente per la ricerca del file da aprire | |
il nome del file da aprire indicato dall'utente | |
metodo che visualizza la finestra di dialogo di salvataggio. Restituisce un risultato di tipo DialogResult. |
Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:
![]() |
elenco a discesa generato dalla proprietà Filter. Il tipo di file proposto per impostazione predefinita è determinato da FilterIndex | |
cartella corrente, impostata da InitialDirectory se questa proprietà è stata specificata | |
nome del file scelto o digitato direttamente dall’utente. Sarà disponibile nella proprietà FileName | |
pulsanti Apri/Annulla. Se viene utilizzato il pulsante Ouvrir, la funzione ShowDialog restituisce il risultato DialogResult.OK |
La procedura di apertura può essere scritta come segue:
Private Sub btnCharger_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCharger.Click
' si carica un file di testo nella casella di immissione
' si configura la finestra di dialogo openfileDialog1
openFileDialog1.InitialDirectory = Application.ExecutablePath
openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
openFileDialog1.FilterIndex = 0
' si visualizza la finestra di dialogo e si recupera il risultato
If openFileDialog1.ShowDialog() = DialogResult.OK Then
' si recupera il nome del file
Dim nomFichier As String = openFileDialog1.FileName
Dim fichier As StreamReader = Nothing
Try
' si apre il file in modalità di lettura
fichier = New StreamReader(nomFichier)
' si legge l'intero file e lo si inserisce in TextBox
txtTexte.Text = fichier.ReadToEnd()
Catch ex As Exception
' problema
MessageBox.Show("Problème à la lecture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' si chiude il file
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Si imposta la cartella iniziale come quella contenente l'eseguibile dell'applicazione:
- Si specificano i tipi di file da presentare
- Si imposta il tipo di file da visualizzare all'inizio
In questo caso, saranno i file di tipo *.txt a essere visualizzati per primi all'utente.
- Viene visualizzata la finestra di dialogo e se ne recupera il risultato
If openFileDialog1.ShowDialog() = DialogResult.OK Then
Mentre la finestra di dialogo è visualizzata, l'utente non ha più accesso al modulo principale (finestra di dialogo cosiddetta modale). L'utente specifica il nome del file da aprire e chiude la finestra di dialogo tramite il pulsante Apri, il pulsante Annulla oppure chiudendo direttamente la finestra. Il risultato del metodo ShowDialog è DialogResult.OK solo se l’utente ha utilizzato il pulsante Ouvrir per chiudere la finestra di dialogo.
- A questo punto, il nome del file da creare si trova ora nella proprietà FileName dell’oggetto openFileDialog1. Si torna quindi alla classica lettura di un file di testo. Si noti il metodo che consente di leggere l’intero file:
- il contenuto del file viene inserito in TextBox txtTexte. Si gestiscono le eccezioni che potrebbero verificarsi.
5.7.2. Finestre di dialogo FontColor e ColorDialog
Proseguiamo l'esempio precedente presentando due nuovi pulsanti:
![]() |
N. | tipo | nome | funzione |
6 | Pulsante | btnCouleur | per impostare il colore dei caratteri di TextBox |
7 | Pulsante | btnPolice | per impostare il carattere di TextBox |
Inseriamo nel modulo un controllo ColorDialog e un controllo FontDialog:

Le classi FontDialog e ColorDialog dispongono di un metodo ShowDialog analogo al metodo ShowDialog delle classi OpenFileDialog e SaveFileDialog. Il metodo ShowDialog della classe ColorDialog consente di scegliere un colore:

Se l’utente chiude la finestra di dialogo con il pulsante OK, il risultato del metodo ShowDialog è DialogResult.OK e il colore selezionato si trova nella proprietà Color dell'oggetto ColorDialog utilizzato. Il metodo ShowDialog della classe FontDialog consente di scegliere un tipo di carattere:

Se l'utente chiude la finestra di dialogo con il pulsante OK, il risultato del metodo ShowDialog è DialogResult.OK e il carattere selezionato si trova nella proprietà Font dell'oggetto FontDialog utilizzato. Abbiamo gli elementi per gestire i clic sui pulsanti Couleur e Police:
Private Sub btnCouleur_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCouleur.Click
' scelta di un colore per il testo
If colorDialog1.ShowDialog() = DialogResult.OK Then
' si modifica la proprietà forecolor di TextBox
txtTexte.ForeColor = colorDialog1.Color
End If
End Sub
Private Sub btnPolice_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnPolice.Click
' scelta di un tipo di carattere
If fontDialog1.ShowDialog() = DialogResult.OK Then
' si modifica la proprietà font di TextBox
txtTexte.Font = fontDialog1.Font
End If
End Sub
5.7.3. Timer
Qui ci proponiamo di scrivere la seguente applicazione:
![]() |
n. | Tipo | Nome | Ruolo |
1 | TextBox, ReadOnly=true | txtChrono | visualizza un cronometro |
2 | Pulsante | btnArretMarche | pulsante Start/Stop del cronometro |
3 | Timer | timer1 | componente che emette un evento ogni secondo |
Il cronometro è in funzione:

Il cronometro è fermo:

Per modificare ogni secondo il contenuto di TextBox e txtChrono, abbiamo bisogno di un componente che generi un evento ogni secondo, evento che potremo intercettare per aggiornare la visualizzazione del cronometro. Questo componente è il Timer:

Una volta installato questo componente nel modulo (nella sezione dei componenti non visivi), nel costruttore del modulo viene creato un oggetto di tipo Timer. La classe System.Windows.Forms.Timer è definita come segue:

Tra le sue proprietà, ne prenderemo in considerazione solo le seguenti:
numero di millisecondi al termine dei quali viene generato un evento Tick. | |
l'evento generato al termine di Interval millisecondi | |
imposta il timer come attivo (true) o inattivo (false) |
Nel nostro esempio il timer si chiama timer1 e timer1.Interval è impostato a 1000 ms (1 s). L'evento Tick si verificherà quindi ogni secondo. Il clic sul pulsante On/Off viene gestito dalla seguente procedura:
Private Sub btnArretMarche_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnArretMarche.Click
' Arresto o avvio?
If btnArretMarche.Text = "Marche" Then
' si annota l'ora di inizio
début = DateTime.Now
' lo si visualizza
txtChrono.Text = "00:00:00"
' si avvia il timer
timer1.Enabled = True
' si modifica la dicitura del pulsante
btnArretMarche.Text = "Arrêt"
' fine
Return
End If '
If btnArretMarche.Text = "Arrêt" Then
' arresto del timer
timer1.Enabled = False
' si modifica il testo del pulsante
btnArretMarche.Text = "Marche"
' fine
Return
End If
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' è trascorso un secondo
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
Il testo del pulsante On/Off è “Off” oppure “On”. È quindi necessario verificare il testo per determinare l’azione da eseguire.
- nel caso di "On", si registra l'ora di inizio in una variabile globale dell'oggetto modulo, si avvia il timer (Enabled=true) e il testo del pulsante passa a "Off".
- Nel caso di "Arresto", si arresta il timer (Enabled=false) e si imposta l'etichetta del pulsante su "Avvio".
Public Class Timer1
Inherits System.Windows.Forms.Form
Private WithEvents timer1 As System.Windows.Forms.Timer
Private WithEvents btnArretMarche As System.Windows.Forms.Button
Private components As System.ComponentModel.IContainer
Private WithEvents txtChrono As System.Windows.Forms.TextBox
Private WithEvents label1 As System.Windows.Forms.Label
' variabili di istanza
Private début As DateTime
L’attributo début sopra indicato è riconosciuto in tutti i metodi della classe. Resta da gestire l’evento Tick sull’oggetto timer1, evento che si verifica ogni secondo:
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' è trascorso un secondo
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
Si calcola il tempo trascorso dall’ora di avvio del cronometro. Si ottiene un oggetto di tipo TimeSpan che rappresenta un intervallo di tempo. Questo deve essere visualizzato nel cronometro nel formato hh:mm:ss. A tal fine utilizziamo le proprietà Hours, Minutes, Seconds dell’oggetto TimeSPan, che rappresentano rispettivamente le ore, i minuti e i secondi della durata che visualizziamo nel formato ToString("d2") per ottenere una visualizzazione a 2 cifre.
5.8. L'esempio IMPOTS
Riprendiamo l’applicazione IMPOTS già trattata due volte. Ora vi aggiungiamo un’interfaccia grafica:
![]() |
I controlli sono i seguenti
n. | tipo | nome | ruolo |
RadioButton | rdOui | spuntare se sposato | |
RadioButton | rdNon | spuntare se non sposato | |
NumericUpDown | incEnfants | numero di figli del contribuente Minimo=0, Massimo=20, Incremento=1 | |
TextBox | txtSalaire | stipendio annuo del contribuente in F | |
TextBox | txtImpots | importo dell'imposta da pagare ReadOnly=true | |
Pulsante | btnCalculer | avvia il calcolo dell'imposta | |
Pulsante | btnEffacer | ripristina il modulo allo stato iniziale al momento del caricamento | |
Pulsante | btnQuitter | per uscire dall'applicazione |
Regole di funzionamento
- il pulsante «Calcola» rimane disattivato finché il campo dello stipendio è vuoto
- se, una volta avviato il calcolo, si riscontra che lo stipendio è errato, viene segnalato l’errore:

Il programma è riportato di seguito. Utilizza la classe impot creata nel capitolo dedicato alle classi. Una parte del codice generato automaticamente da VS.NET non è stata qui riprodotta.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
' opzioni
Option Explicit On
Option Strict On
' spazi dei nomi
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
' classe modulo
Public Class frmImpots
Inherits System.Windows.Forms.Form
Private WithEvents label1 As System.Windows.Forms.Label
Private WithEvents rdOui As System.Windows.Forms.RadioButton
Private WithEvents rdNon As System.Windows.Forms.RadioButton
Private WithEvents label2 As System.Windows.Forms.Label
Private WithEvents txtSalaire As System.Windows.Forms.TextBox
Private WithEvents label3 As System.Windows.Forms.Label
Private WithEvents label4 As System.Windows.Forms.Label
Private WithEvents groupBox1 As System.Windows.Forms.GroupBox
Private WithEvents btnCalculer As System.Windows.Forms.Button
Private WithEvents btnEffacer As System.Windows.Forms.Button
Private WithEvents btnQuitter As System.Windows.Forms.Button
Private WithEvents txtImpots As System.Windows.Forms.TextBox
Private components As System.ComponentModel.Container = Nothing
Private WithEvents incEnfants As System.Windows.Forms.NumericUpDown
' tabelle di dati necessarie per il calcolo dell'imposta
Private limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Private coeffR() As Decimal = {0D, 0.05D, 0.1D, 0.15D, 0.2D, 0.25D, 0.3D, 0.35D, 0.4D, 0.45D, 0.55D, 0.5D, 0.6D, 0.65D}
Private coeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' oggetto imposta
Private objImpôt As impot = Nothing
Public Sub New()
InitializeComponent()
' inizializzazione del modulo
btnEffacer_Click(Nothing, Nothing)
btnCalculer.Enabled = False
' creazione di un oggetto imposta
Try
objImpôt = New impot(limites, coeffR, coeffN)
Catch ex As Exception
MessageBox.Show("Impossible de créer l'objet impôt (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
' si disabilita il campo di immissione dello stipendio
txtSalaire.Enabled = False
End Try 'try-catch
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
....
End Sub
Private Sub InitializeComponent()
Me.btnQuitter = New System.Windows.Forms.Button
Me.groupBox1 = New System.Windows.Forms.GroupBox
Me.btnEffacer = New System.Windows.Forms.Button
Me.btnCalculer = New System.Windows.Forms.Button
Me.txtSalaire = New System.Windows.Forms.TextBox
Me.label1 = New System.Windows.Forms.Label
Me.label2 = New System.Windows.Forms.Label
Me.label3 = New System.Windows.Forms.Label
Me.rdNon = New System.Windows.Forms.RadioButton
Me.txtImpots = New System.Windows.Forms.TextBox
Me.label4 = New System.Windows.Forms.Label
Me.rdOui = New System.Windows.Forms.RadioButton
Me.incEnfants = New System.Windows.Forms.NumericUpDown
Me.groupBox1.SuspendLayout()
CType(Me.incEnfants, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
....
End Sub 'InitializeComponent
Public Shared Sub Main()
Application.Run(New frmImpots)
End Sub 'Main
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' azzeramento del modulo
incEnfants.Value = 0
txtSalaire.Text = ""
txtImpots.Text = ""
rdNon.Checked = True
End Sub 'btnEffacer_Click
Private Sub txtSalaire_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSalaire.TextChanged
' stato del pulsante «Calcola»
btnCalculer.Enabled = txtSalaire.Text.Trim() <> ""
End Sub 'txtSalaire_TextChanged
Private Sub btnQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnQuitter.Click
' fine dell'applicazione
Application.Exit()
End Sub 'btnQuitter_Click
Private Sub btnCalculer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCalculer.Click
' Lo stipendio è corretto?
Dim intSalaire As Integer = 0
Try
' recupero dello stipendio
intSalaire = Integer.Parse(txtSalaire.Text)
' deve essere >=0
If intSalaire < 0 Then
Throw New Exception("")
End If
Catch ex As Exception
' messaggio di errore
MessageBox.Show(Me, "Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error)
' focus sul campo errato
txtSalaire.Focus()
' selezione del testo nel campo di immissione
txtSalaire.SelectAll()
' ritorno all'interfaccia visiva
Return
End Try 'try-catch
' lo stipendio è corretto - si calcola l'imposta
txtImpots.Text = "" & CLng(objImpôt.calculer(rdOui.Checked, CInt(incEnfants.Value), intSalaire))
End Sub 'btnCalculer_Click
End Class
Qui utilizziamo l'assembly impots.dll, risultato della compilazione della classe impots del capitolo 2. Ricordiamo che questo assembly può essere generato in modalità console tramite il comando
Questo comando genera il file impots.dll denominato «assemblaggio». Tale assemblaggio può essere successivamente utilizzato in diversi progetti. Qui, nel nostro progetto denominato VS.NET, utilizziamo la finestra delle proprietà del progetto:

Per aggiungere un riferimento (un assieme), facciamo clic con il tasto destro del mouse sul gruppo chiave «Riferimenti» sopra indicato, selezioniamo l’opzione [Ajouter une référence] e indichiamo l’assieme [impots.dll] che abbiamo provveduto a inserire nella cartella del progetto:
dos>dir
01/03/2004 14:39 9 250 gui_impots.vb
01/03/2004 14:37 4 096 impots.dll
01/03/2004 14:41 12 288 gui_impots.exe
Una volta incluso l’assembly [impots.dll] nel progetto, la classe [impots] diventa nota al progetto. In precedenza non lo era. Un altro metodo consiste nell’includere il file sorgente impots.vb nel progetto. A tal fine, nella finestra delle proprietà del progetto, si fa clic con il tasto destro del mouse sul progetto, si seleziona l’opzione [Ajouter/Ajouter un élément existant] e si indica il file impots.vb.















































