5. Interfacce grafiche con VB.NET e VS.NET
In questa sede, intendiamo illustrare come realizzare interfacce grafiche utente con VB.NET. In primo luogo, esamineremo le classi principali della piattaforma .NET che ci consentono di creare un'interfaccia utente grafica. Inizialmente, non utilizzeremo alcun strumento di generazione automatica. Successivamente utilizzeremo Visual Studio.NET (VS.NET), uno strumento di sviluppo Microsoft che facilita lo sviluppo di applicazioni utilizzando i linguaggi .NET, in particolare la creazione di interfacce utente grafiche. La versione di VS.NET utilizzata è quella in lingua inglese.
5.1. Nozioni di base sulle interfacce utente grafiche
5.1.1. Una finestra semplice
Consideriamo il seguente codice:
' options
Option Strict On
Option Explicit On
' namespaces
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' the form class
Public Class Form1
Inherits Form
' the manufacturer
Public Sub New()
' window title
Me.Text = "Mon premier formulaire"
' window dimensions
Me.Size = New System.Drawing.Size(300, 100)
End Sub
' test function
Public Shared Sub Main(ByVal args() As String)
' the form is displayed
Application.Run(New Form1)
End Sub
End Class
Il codice precedente viene compilato e quindi eseguito
L'esecuzione visualizza la seguente finestra:

Un'interfaccia utente grafica deriva generalmente dalla classe base System.Windows.Forms.Form:
La classe base Form definisce una finestra di base con pulsanti di chiusura, ingrandimento/riduzione a icona, dimensioni regolabili, ecc., e gestisce gli eventi su questi oggetti grafici. Qui specializziamo la classe base impostandone il titolo, la larghezza (300) e l'altezza (100). Ciò avviene nel suo costruttore:
Public Sub New()
' window title
Me.Text = "Mon premier formulaire"
' window dimensions
Me.Size = New System.Drawing.Size(300, 100)
End Sub
Il titolo della finestra viene impostato dalla proprietà Text, mentre le dimensioni dalla proprietà Size. La proprietà Size è definita nello spazio dei nomi System.Drawing ed è una struttura. La procedura Main avvia l'applicazione grafica come segue:
Application.Run(New Form1)
Viene creato e visualizzato un modulo di tipo Form1, quindi l'applicazione ascolta gli eventi che si verificano sul modulo (clic, movimenti del mouse, ecc.) ed esegue quelli gestiti dal modulo. In questo caso, il nostro modulo non gestisce alcun evento oltre a quelli gestiti dalla classe Form di base (clic sui pulsanti di chiusura, ingrandimento/riduzione a icona, ridimensionamento della finestra, spostamento della finestra, ecc.).
5.1.2. Un modulo con un pulsante
Ora aggiungiamo un pulsante alla nostra finestra:
' options
Option Strict On
Option Explicit On
' namespaces
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' the form class
Public Class Form1
Inherits Form
' attributes
Private cmdTest As Button
' the manufacturer
Public Sub New()
' the title
Me.Text = "Mon premier formulaire"
' dimensions
Me.Size = New System.Drawing.Size(300, 100)
' a button
' creation
Me.cmdTest = New Button
' position
cmdTest.Location = New System.Drawing.Point(110, 20)
' size
cmdTest.Size = New System.Drawing.Size(80, 30)
' wording
cmdTest.Text = "Test"
' event manager
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' add button to form
Me.Controls.Add(cmdTest)
End Sub
' event manager
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' there was a click on the button - we say it
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' test function
Public Shared Sub Main(ByVal args() As String)
' the form is displayed
Application.Run(New Form1)
End Sub
End Class
Abbiamo aggiunto un pulsante al modulo:
' un bouton
' création
Me.cmdTest = New Button
' position
cmdTest.Location = New System.Drawing.Point(110, 20)
' taille
cmdTest.Size = New System.Drawing.Size(80, 30)
' libellé
cmdTest.Text = "Test"
' gestionnaire d'évt
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' ajout bouton au formulaire
Me.Controls.Add(cmdTest)
La proprietà Location imposta le coordinate (110,20) dell'angolo superiore sinistro del pulsante utilizzando una struttura Point. La larghezza e l'altezza del pulsante sono impostate su (80,30) utilizzando una struttura Size. La proprietà Text del pulsante imposta l'etichetta del pulsante. La classe Button ha 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 deve avere la firma del delegato [EventHandler]. In questo caso, quando si fa clic sul pulsante cmdTest, verrà chiamato il metodo cmdTest_Click. Questo è definito come segue, in conformità con il precedente modello EventHandler:
' event manager
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' there was a click on the button - we say it
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Visualizziamo semplicemente 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 viene utilizzata per 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
testo | il messaggio da visualizzare |
caption | titolo della finestra |
pulsanti | i pulsanti nella finestra |
icona | l'icona nella finestra |
Il parametro buttons può assumere valori dalle seguenti costanti:
costante | pulsanti |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
Il parametro icon può assumere valori corrispondenti alle seguenti costanti:
![]() | come sopra Stop | ||
come Avviso | ![]() | ||
come Asterisk | ![]() | ||
![]() | Come la mano | ||
![]() |
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 determinare quale pulsante l'utente ha cliccato per chiudere la finestra MessageBox, scriviamo:
dim res as DialogResult=MessageBox.Show(..)
if res=DialogResult.Yes then
' he pressed the yes button
...
end if
5.2. Creazione di un'interfaccia utente grafica con Visual Studio.NET
Ripasseremo alcuni degli esempi visti in precedenza, questa volta realizzandoli con Visual Studio.NET.
5.2.1. Creazione iniziale del progetto
- Avviare VS.NET e selezionare File/Nuovo/Progetto

- Specificare le caratteristiche del progetto
![]() |
- Seleziona il tipo di progetto che desideri creare; in questo caso, un progetto VB.NET (1)
- Seleziona il tipo di applicazione che desideri creare; in questo caso, un'applicazione Windows (2)
- Indica la cartella in cui desideri inserire la sottocartella del progetto (3)
- Inserisci il nome del progetto (4). Questo sarà anche il nome della cartella che conterrà i file del progetto
- Il nome di questa cartella viene visualizzato in (5)
- Vengono quindi create diverse cartelle e file all'interno della cartella i4:
sottocartelle della cartella project1 ![]() |
Di questi file, solo uno è rilevante: il file form1.cs, che è il file sorgente associato al modulo creato da VS.NET. Torneremo su questo punto più avanti.
5.2.2. Le finestre dell'interfaccia di VS.NET
L'interfaccia di VS.NET ora mostra alcuni elementi del nostro progetto i4:
Abbiamo una finestra di progettazione dell'interfaccia utente grafica:
![]() |
Trascinando i controlli dalla barra degli strumenti (Toolbox 2) e rilasciandoli nel riquadro della finestra (1), possiamo costruire un'interfaccia utente grafica. Se passiamo il mouse sopra la "Toolbox", questa si espande per mostrare una serie di controlli:

Per ora, non ne useremo nessuno. Sempre nella schermata di VS.NET, troviamo la finestra “Explorer Solution”:

All'inizio non useremo molto questa finestra. Essa mostra tutti i file che compongono il progetto. Ci interessa solo uno di essi: il file sorgente del nostro programma, in questo caso Form1.vb. Facendo clic con il tasto destro su Form1.vb si apre un menu che consente di accedere al codice sorgente della nostra interfaccia grafica (View Code) o all'interfaccia grafica stessa (Form Designer):

È possibile accedere a entrambi direttamente dalla finestra "Esplora soluzioni":
![]() | ![]() |
Le finestre aperte si "impilano" nella finestra di progettazione principale:

In questo caso, Form1.vb[Design] si riferisce alla finestra di progettazione e Form1.vb alla finestra del codice. È sufficiente fare clic su una delle schede per passare da una finestra all'altra. Un'altra finestra importante visualizzata sullo schermo di VS.NET è la finestra Proprietà:

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

Include le finestre principali appena descritte, insieme alle relative scorciatoie da tastiera.
5.2.3. Esecuzione di un progetto
Anche se non abbiamo scritto alcun codice, abbiamo un progetto eseguibile. Premere F5 o Debug/Avvia per eseguirlo. Si ottiene 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 (View/Code) della nostra applicazione:
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Code généré par le Concepteur Windows Form "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after InitializeComponent() call
End Sub
'The substituted method Disposes of the form to clean up the list of components.
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
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'REMARQUE: the following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "Form2"
End Sub
#End Region
End Class
Un'interfaccia utente grafica deriva dalla classe base System.Windows.Forms.Form:
La classe base Form definisce una finestra di base con pulsanti di chiusura e di ingrandimento/riduzione a icona, dimensioni regolabili e altro ancora, e gestisce gli eventi su questi oggetti grafici. Il costruttore del form utilizza un metodo InitializeComponent in cui vengono creati e inizializzati i controlli del form.
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after InitializeComponent() call
End Sub
Qualsiasi altra operazione da eseguire nel costruttore 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 viene impostato dalla proprietà Text e le dimensioni dalla proprietà Size. Size è definita nello spazio dei nomi System.Drawing ed è una struttura. Per eseguire questa applicazione, dobbiamo definire il modulo principale del progetto. Per farlo, utilizziamo l'opzione [Progetti/Proprietà]:

In [Startup Object], specifichiamo [Form1], ovvero il form appena creato. Per eseguire l'applicazione, utilizziamo l'opzione [Debug/Start]:

5.2.5. Compilazione in una finestra del prompt dei comandi
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' cannot be found in 'Form1'.
Il compilatore indica che non riesce a trovare la procedura [Main]. In effetti, VS.NET non l'ha generata. Tuttavia, l'abbiamo già incontrata negli esempi precedenti. Ha la seguente forma:
Shared Sub Main()
' launch application
Application.Run(New Form1) ' where Form1 is the form
End Sub
Aggiungiamo il codice precedente a [Form1.vb] 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)
~~~~~~~~~~~
Questa volta, il nome [Application] è sconosciuto. Ciò significa semplicemente che non abbiamo importato il suo spazio dei nomi [System.Windows.Forms]. Aggiungiamo la seguente istruzione:
quindi ricompiliamo:
Questa volta funziona. Eseguiamolo:

Viene creato e visualizzato un modulo di tipo Form1. È possibile evitare di aggiungere la procedura [Main] utilizzando l'opzione /m del compilatore, che consente di specificare la classe da eseguire se eredita da System.Windows.Forms:
L'opzione /m:form2 specifica che la classe da eseguire è quella denominata [form2].
5.2.6. Gestione degli eventi
Una volta visualizzato il modulo, l'applicazione ascolta gli eventi che si verificano sul modulo (clic, movimenti del mouse, ecc.) ed esegue quelli gestiti dal modulo. In questo caso, il nostro modulo non gestisce alcun evento oltre a quelli gestiti dalla classe base Form (clic sui pulsanti di chiusura, pulsanti di ingrandimento/riduzione a icona, ridimensionamento della finestra, spostamento della finestra, ecc.). Il modulo generato utilizza un attributo components che non viene utilizzato in nessun punto. Anche il metodo Dispose non è necessario in questo caso. Lo stesso vale per alcuni spazi dei nomi (Collections, ComponentModel, Data) che vengono 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
' manufacturer
Public Sub New()
' building the form with its components
InitializeComponent()
End Sub
Private Sub InitializeComponent()
' window size
Me.Size = New System.Drawing.Size(300, 300)
' window title
Me.Text = "Form1"
End Sub
Shared Sub Main()
' launch application
Application.Run(New Form1)
End Sub
End Class
5.2.7. Conclusione
Ora accetteremo il codice generato da VS.NET così com'è e aggiungeremo semplicemente il nostro codice, in particolare per gestire gli eventi relativi ai vari controlli presenti nel form.
5.3. Finestra con campo di immissione, pulsante ed etichetta
5.3.1. Progettazione grafica
Nell'esempio precedente non abbiamo inserito alcun componente nella finestra. Inizieremo un nuovo progetto denominato interface2. A tal fine seguiremo la procedura descritta 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 | lblInput | Etichetta | un'etichetta |
2 | txtInput | Casella di testo | un campo di immissione |
3 | btnDisplay | Pulsante | per visualizzare il contenuto della casella di testo txtSaisie in una finestra di dialogo |
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 Proprietà per accedere alle proprietà della finestra:

La finestra Proprietà apparirà quindi sulla destra:

Vale la pena notare alcune di queste proprietà:
per impostare il colore di sfondo della finestra | |
per impostare il colore della grafica 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 del testo nella finestra | |
per impostare il nome della finestra |
Qui impostiamo le proprietà Text e Name:
Cerniere e bottoni - 1 | |
frmInputButtons |
Utilizzo della barra "Toolbox"
- seleziona i componenti che ti servono
- trascinarli nella finestra e impostare le dimensioni corrette
![]() | ![]() |
Una volta selezionato il componente dalla "casella degli strumenti", usa il tasto "Esc" per nascondere la barra degli strumenti, quindi trascinare e ridimensiona il componente. Ripeti l'operazione per i tre componenti necessari: Label, TextBox, Button. Per allineare e ridimensionare correttamente i componenti, usa il menu Formato: | ![]() |
Il processo di formattazione funziona come segue:
L'opzione Allinea consente di allineare i componenti | ![]() |
L'opzione "Usa stessa dimensione" garantisce che i componenti abbiano la stessa altezza o la stessa larghezza: | ![]() |
L'opzione "Spaziatura orizzontale", ad esempio, per allineare i componenti orizzontalmente con spaziatura uguale tra di essi. Lo stesso vale all'opzione Spaziatura verticale per l'allineamento verticale. L'opzione Centra nel modulo consente di centrare un componente in orizzontale o verticalmente all'interno della finestra: | ![]() |
Una volta che i componenti sono stati posizionati nella finestra, impostare le loro proprietà. Per farlo, fare clic con il tasto destro del mouse sul componente e selezionare l'opzione Proprietà:
Selezionare il componente per aprire per aprire la finestra delle Proprietà. In questa finestra, modificare le seguenti proprietà: nome: lblSaisie, testo: Saisie
Selezionare il componente per aprire la relativa finestra delle proprietà. In questa finestra, modificare le seguenti proprietà: nome: txtSaisie, testo: lasciare vuoto
nome: cmdAfficher, testo: Visualizza
testo: Inserimenti e pulsanti - 1 | ![]() |
Possiamo eseguire (Ctrl-F5) il nostro progetto per dare una prima occhiata alla finestra in azione: | ![]() |
Chiudere la finestra. Dobbiamo ancora scrivere la procedura associata al clic sul pulsante Visualizza.
5.3.2. Gestione degli eventi del modulo
Diamo un'occhiata al codice generato dal visual designer:
...
Public Class frmSaisiesBoutons
Inherits System.Windows.Forms.Form
' components
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
' manufacturer
Public Sub New()
InitializeComponent()
End Sub
...
' component initialization
Private Sub InitializeComponent()
...
End Sub
End Class
Innanzitutto, si noti la dichiarazione specifica dei componenti:
- la parola chiave Friend indica che il componente è visibile a tutte le classi del progetto
- la parola chiave WithEvents indica che il componente genera eventi. Vedremo ora come gestire questi eventi
Visualizzare la finestra del codice del modulo (Visualizza/Codice o F7):
![]() |
La finestra sopra riportata mostra due elenchi a discesa (1) e (2). L'elenco (1) è l'elenco dei componenti del modulo:

L'elenco (2) mostra 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 di eventi nella finestra del codice e posiziona il cursore su di esso. Per accedere ai gestori degli altri eventi, andare alla finestra del codice, selezionare il componente dall'elenco (1) e selezionare l'evento da (2). VB.NET genera quindi lo scheletro del gestore di eventi o posiziona il cursore 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 assegna un nome al gestore di eventi per l'evento E del componente C. È possibile modificare questo nome, se lo si desidera. Tuttavia, questa operazione non è consigliata. Gli sviluppatori VB mantengono generalmente il nome generato da VB, il che garantisce la coerenza nella denominazione in tutti i programmi VB. L'associazione della procedura btnAfficher_Click con l'evento Click del componente btnAfficher non avviene tramite il nome della procedura, ma tramite la parola chiave handles:
Handles btnAfficher.Click
Nel codice sopra riportato, la parola chiave handles specifica che la procedura gestisce l'evento Click del componente btnAfficher. Il gestore di eventi ha due parametri:
l'oggetto che ha generato l'evento (in questo caso, il pulsante) | |
un oggetto EventArgs che descrive in dettaglio l'evento verificatosi |
Qui non useremo nessuno di questi parametri. Non 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)
' the text entered in the TxtSaisie input box is displayed
MessageBox.Show("texte saisi= " + txtsaisie.Text, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Quando si esegue l'applicazione, si verifica 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
...
' event manager click on cmdAfficher button
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
...
' event manager click on cmdAfficher button
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 la procedura denominata btnAfficher_Click all'evento btnAfficher.Click. Inoltre, il componente btnAfficher non richiede più la 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 in fase di esecuzione. Ciò è utile in un framework di eventi produttore-consumatore. Un oggetto produce un evento specifico che può essere di interesse per altri oggetti. Questi oggetti si iscrivono al produttore per ricevere l'evento (ad esempio, una temperatura che supera una soglia critica). Durante l'esecuzione dell'applicazione, al produttore dell'evento verrà richiesto di eseguire varie istruzioni:
dove E è l'evento generato dal produttore e P1 è una delle procedure appartenenti ai vari oggetti che consumano questo evento. Avremo l'opportunità di riesaminare un'applicazione di eventi produttore-consumatore in un capitolo successivo.
5.3.4. Conclusione
Dai due progetti studiati, possiamo concludere che una volta costruita l'interfaccia grafica utente con VS.NET, il compito dello sviluppatore è quello di scrivere i gestori di eventi per gli eventi che desidera gestire all'interno di tale interfaccia. D'ora in poi, presenteremo solo il codice per questi gestori.
5.4. Alcuni componenti utili
Presenteremo ora varie applicazioni che utilizzano i componenti più comuni per esplorarne i metodi e le proprietà principali. Per ogni applicazione, presenteremo l'interfaccia utente grafica e il codice pertinente, in particolare i gestori di eventi.
5.4.1. Modulo
Inizieremo introducendo il componente essenziale: il modulo su cui vengono posizionati i componenti. Abbiamo già trattato alcune delle sue proprietà di base. Qui ci concentreremo su alcuni importanti eventi del 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 viene chiuso. Questa chiusura può comunque essere interrotta a livello di programmazione. Creiamo un modulo denominato Form1 senza alcun componente:

Gestiamo i tre eventi precedenti:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' initial form loading
MessageBox.Show("Evt Load", "Load")
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
' the form is closing
MessageBox.Show("Evt Closing", "Closing")
' confirmation requested
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
' the form is closing
MessageBox.Show("Evt Closed", "Closed")
End Sub
Utilizziamo la funzione MessageBox per ricevere una notifica dei vari eventi. L'evento Closing si verifica quando l'utente chiude la finestra. | ![]() |
A quel punto chiediamo se desidera davvero uscire dall'applicazione: | ![]() |
Se risponde No, impostiamo la proprietà Cancel dell'oggetto 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. Controlli Label e TextBox
Abbiamo già incontrato questi due componenti. Label è un componente di testo e TextBox è un componente di campo di immissione. La loro proprietà principale è Text, che si riferisce al contenuto del campo di immissione o al testo dell'etichetta. Questa proprietà è di lettura/scrittura. L'evento tipicamente utilizzato per TextBox è TextChanged, che segnala che l'utente ha modificato il campo di immissione. Ecco un esempio che utilizza l'evento TextChanged per tracciare le modifiche in un campo di immissione:
![]() |
No. | tipo | nome | ruolo |
1 | Casella di testo | txtInput | campo di immissione |
2 | Etichetta | lblControl | visualizza il testo di 1 in tempo reale |
3 | Pulsante | cmdClear | per cancellare i campi 1 e 2 |
4 | Pulsante | cmdExit | per uscire dall'applicazione |
Il codice rilevante per questa applicazione è costituito dai gestori di eventi:
' click on btn quit
Private Sub cmdQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdQuitter.Click
' click on the Quit button - exit the application
Application.Exit()
End Sub
' field modification txtSaisie
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' the content of TextBox has changed - copy it to Label lblControle
lblControle.Text = txtSaisie.Text
End Sub
' click on btn delete
Private Sub cmdEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdEffacer.Click
' delete the contents of the input box
txtSaisie.Text = ""
End Sub
' a key has been pressed
Private Sub txtSaisie_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles txtSaisie.KeyPress
' see which key has been pressed
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 come l'applicazione venga chiusa nella procedura cmdQuitter_Click: Application.Exit(). L'esempio seguente utilizza una casella di testo su più righe:
![]() |
L'elenco dei controlli è il seguente:
N. | Tipo | nome | ruolo |
1 | Casella di testo | txtMultiLines | campo di immissione multilinea |
2 | Casella di testo | txtAdd | campo di immissione a riga singola |
3 | Pulsante | btnAdd | Sottrai 2 da 1 |
Per rendere una casella di testo multilinea, imposta le seguenti proprietà del controllo:
per consentire più righe di testo | |
per specificare se il controllo deve avere le barre di scorrimento (Orizzontale, Verticale, Entrambe) o meno (Nessuna) | |
se impostato su true, il tasto Invio passerà alla riga successiva | |
se impostato su true, il tasto Tab inserirà un tabulatore nel testo |
Il codice rilevante è quello che gestisce il clic sul pulsante [Add] e quello che gestisce le modifiche al campo di immissione [txtAdd]:
' évt btnAjouter_Click
Private Sub btnAjouter_Click1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' add the content of txtAjout to that of txtMultilignes
txtMultilignes.Text &= txtAjout.Text
txtAjout.Text = ""
End Sub
' evt txtAjout_TextChanged
Private Sub txtAjout_TextChanged1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtAjout.TextChanged
' set the state of the Add button
btnAjouter.Enabled = txtAjout.Text.Trim() <> ""
End Sub
5.4.3. Elenchi a discesa della casella combinata
![]() | ![]() |
Un componente ComboBox è un elenco a discesa combinato con un campo di immissione: l'utente può selezionare una voce dall'elenco (2) oppure digitare del testo nel campo (1). Esistono tre tipi di ComboBox definiti dalla proprietà Style:
elenco non a discesa con casella di modifica | |
elenco a discesa con casella di modifica | |
elenco a discesa senza casella di modifica |
Per impostazione predefinita, il tipo di una ComboBox è DropDown. Per ulteriori informazioni sulla classe ComboBox, digitare ComboBox nell'indice della Guida (Guida/Indice). La classe ComboBox dispone di un unico costruttore:
Public Sub New() | crea un oggetto ComboBox vuoto |
Gli elementi presenti nel ComboBox sono disponibili nella proprietà Items:
Si tratta di una proprietà indicizzata, dove Items(i) si riferisce all'i-esimo elemento nel Combo. Sia C un Combo e C.Items il suo elenco di elementi. Abbiamo le seguenti proprietà:
numero di elementi nella ComboBox | |
elemento i del ComboBox | |
aggiunge l'oggetto o come ultimo elemento della casella combinata | |
aggiunge un array di oggetti alla fine del menu a discesa | |
aggiunge l'oggetto o alla posizione i nel menu a discesa | |
rimuove l'elemento i dalla casella combinata | |
rimuove l'oggetto o dalla casella combinata | |
cancella tutti gli elementi dalla casella combinata | |
restituisce la posizione i dell'oggetto o nella casella combinata |
Potrebbe sembrare sorprendente che una casella combinata possa contenere oggetti quando solitamente contiene stringhe. Visivamente, è effettivamente così. Se una casella combinata contiene un oggetto obj, visualizza la stringa obj.ToString(). Ricordiamo che ogni oggetto ha un metodo ToString ereditato dalla classe Object, che restituisce una stringa che "rappresenta" l'oggetto. L'elemento selezionato nella casella combinata C è C.SelectedItem o C.Items(C.SelectedIndex), dove C.SelectedIndex è l'indice dell'elemento selezionato, a partire da zero per il primo elemento.
Quando un elemento viene selezionato dall'elenco a discesa, viene attivato l'evento SelectedIndexChanged, che può quindi essere utilizzato per rilevare una modifica nella selezione della casella combinata. Nell'applicazione seguente, utilizziamo questo evento per visualizzare l'elemento che è stato selezionato dall'elenco.

Mostriamo solo il codice rilevante per la finestra. Nel costruttore del modulo, popoliamo la casella combinata:
Public Sub New()
' création formulaire
InitializeComponent()
' remplissage combo
cmbNombres.Items.AddRange(New String() {"zéro", "un", "deux", "trois", "quatre"})
' nous sélectionnons le 1er élément de la liste
cmbNombres.SelectedIndex = 0
End Sub
Gestiamo l'evento SelectedIndexChanged della casella combinata, che segnala che è stato selezionato un nuovo elemento:
Private Sub cmbNombres_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmbNombres.SelectedIndexChanged
' the selected item has changed - it is displayed
MessageBox.Show("Elément sélectionné : (" & cmbNombres.SelectedItem.ToString & "," & cmbNombres.SelectedIndex & ")", "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
5.4.4. Componente ListBox
Proponiamo di realizzare la seguente interfaccia:
![]() |
I componenti di questa finestra sono i seguenti:
N. | Tipo | Nome | ruolo/proprietà |
0 | Modulo | Form1 | modulo - BorderStyle=FixedSingle |
1 | Casella di testo | txtInput | campo di immissione |
2 | Pulsante | btnAdd | pulsante per aggiungere il contenuto del campo di immissione 1 all'elenco 3 |
3 | ListBox | listBox1 | Lista 1 |
4 | Casella di riepilogo | listBox2 | elenco 2 |
5 | Pulsante | btn1TO2 | trasferisce gli elementi selezionati dall'elenco 1 all'elenco 2 |
6 | Pulsante | cmd2T0 | fa l'opposto |
7 | Pulsante | btnClear1 | cancella la lista 1 |
8 | Pulsante | btnClear2 | cancella l'elenco 2 |
- L'utente digita il testo nel campo 1. Lo aggiunge all'elenco 1 utilizzando il pulsante Aggiungi (2). Il campo di immissione (1) viene quindi cancellato e l'utente può aggiungere una nuova voce.
- È possibile trasferire voci da un elenco all'altro selezionando la voce da trasferire in uno degli elenchi e scegliendo il pulsante di trasferimento appropriato 5 o 6. La voce trasferita viene aggiunta alla fine dell'elenco di destinazione e rimossa dall'elenco di origine.
- È possibile fare doppio clic su un elemento nell'Elenco 1. L'elemento viene quindi trasferito nella casella di immissione per la modifica e rimosso dall'Elenco 1.
I pulsanti sono abilitati o disabilitati in base alle seguenti regole:
- il pulsante Aggiungi è abilitato solo se nel campo di immissione è presente del testo
- Il pulsante 5 per il trasferimento dall'Elenco 1 all'Elenco 2 è abilitato solo se è selezionato un elemento nell'Elenco 1
- Il pulsante 6 per il trasferimento dall'elenco 2 all'elenco 1 è attivo solo se nell'elenco 2 è selezionata una voce
- I pulsanti 7 e 8 per cancellare le liste 1 e 2 sono attivi solo se la lista da cancellare contiene voci.
In base alle condizioni di cui sopra, tutti i pulsanti devono essere disabilitati all'avvio dell'applicazione. Ciò significa che la proprietà Enabled dei pulsanti deve essere impostata su false. Ciò può essere fatto in fase di progettazione, il che genererà il codice corrispondente nel metodo InitializeComponent, oppure possiamo farlo noi stessi nel costruttore come mostrato di seguito:
Public Sub New()
' initial form creation
InitializeComponent()
' additional initializations
' a number of buttons are disabled
btnAjouter.Enabled = False
btn1TO2.Enabled = False
btn2TO1.Enabled = False
btnEffacer1.Enabled = False
btnEffacer2.Enabled = False
End Sub
Lo stato del pulsante Aggiungi è controllato dal contenuto del campo di immissione testo. L'evento TextChanged ci permette di monitorare le modifiche apportate a questo contenuto:
' change in field txtsaisie
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' the content of txtSaisie has changed
' the Add button is only lit if the entry is non-empty
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 controllano:
' chgt selected item without listbox1
Private Sub listBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox1.SelectedIndexChanged
' an item has been selected
' switch on the 1 to 2 transfer button
btn1TO2.Enabled = True
End Sub
' chgt selected item without listbox2
Private Sub listBox2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox2.SelectedIndexChanged
' an item has been selected
' switch on the 2 to 1 transfer button
btn2TO1.Enabled = True
End Sub
Il codice associato al clic sul pulsante Aggiungi è il seguente:
' click on btn Add
Private Sub btnAjouter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' add a new element to list 1
listBox1.Items.Add(txtSaisie.Text.Trim())
' raz de la saisie
txtSaisie.Text = ""
' List 1 is not empty
btnEffacer1.Enabled = True
' return focus to input box
txtSaisie.Focus()
End Sub
Si noti il metodo Focus, che consente di impostare il "focus" su un controllo del modulo. Il codice associato al clic sui pulsanti Cancella:
' click on btn Delete1
Private Sub btnEffacer1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer1.Click
' delete list 1
listBox1.Items.Clear()
btnEffacer1.Enabled = False
End Sub
' click on btn delete2
Private Sub btnEffacer2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' delete list 2
listBox2.Items.Clear()
btnEffacer2.Enabled = False
End Sub
Il codice per trasferire gli elementi selezionati da un elenco a un altro:
' click on btn btn1to2
Private Sub btn1TO2_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn1TO2.Click
' transfer the item selected in List 1 to List 2
transfert(listBox1, listBox2)
' delete buttons
btnEffacer2.Enabled = True
btnEffacer1.Enabled = listBox1.Items.Count <> 0
' transfer buttons
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' click on btn btn2to1
Private Sub btn2TO1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn2TO1.Click
' transfer item selected in List 2 to List 1
transfert(listBox2, listBox1)
' delete buttons
btnEffacer1.Enabled = True
btnEffacer2.Enabled = listBox2.Items.Count <> 0
' transfer buttons
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' transfer
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
' transfer selected item from list 1 to list l2
' a selected item?
If l1.SelectedIndex = -1 Then Return
' addition to l2
l2.Items.Add(l1.SelectedItem)
' deletion in l1
l1.Items.RemoveAt(l1.SelectedIndex)
End Sub
Per prima cosa, creiamo un metodo
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
che trasferisce l'elemento selezionato dall'elenco l1 all'elenco l2. Questo ci permette di utilizzare un unico metodo invece di due per trasferire un elemento da ListBox1 a ListBox2 o da ListBox2 a ListBox1. Prima di eseguire il trasferimento, ci assicuriamo che un elemento sia effettivamente selezionato nell'elenco l1:
' un élément sélectionné ?
If l1.SelectedIndex = -1 Then Return
La proprietà SelectedIndex è -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
trasferiamo il contenuto della lista X alla lista Y e aggiorniamo lo stato di alcuni controlli per riflettere il nuovo stato delle liste.
5.4.5. Caselle di controllo CheckBox, pulsanti di opzione ButtonRadio
Proponiamo di scrivere la seguente applicazione:
![]() |
I componenti della finestra sono i seguenti:
N. | Tipo | nome | ruolo |
1 | RadioButton | radioButton1 pulsante di opzione 2 radioButton3 | 3 pulsanti di opzione |
2 | casella di controllo | casella di controllo1 checkBox2 checkbox3 | 3 caselle di controllo |
3 | Casella di riepilogo | lstValues | un elenco |
Se creiamo 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, quando è vera, significa che il controllo è selezionato. Qui abbiamo utilizzato un unico metodo per gestire tutti e sei gli eventi CheckChanged; il metodo visualizza:
' poster
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
' displays radio button or checkbox status
' is this a checkbox?
If (TypeOf (sender) Is CheckBox) Then
Dim chk As CheckBox = CType(sender, CheckBox)
lstValeurs.Items.Insert(0, chk.Name & "=" & chk.Checked)
End If
' is it a radiobutton?
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 (sender) Is CheckBox ci permette di verificare se l'oggetto sender è di tipo CheckBox. Questo ci consente quindi di convertirlo nel tipo esatto di sender. Il metodo visualizza il nome del componente che ha generato l'evento e il valore della sua proprietà Checked nell'elenco lstValeurs. In fase di esecuzione, si osserva che facendo clic su un pulsante di opzione si attivano due eventi CheckChanged: uno sul pulsante precedentemente selezionato, che diventa "deselezionato", e l'altro sul nuovo pulsante, che diventa "selezionato".
5.4.6. Controlli ScrollBar
Esistono diversi tipi di barre di scorrimento: la barra di scorrimento orizzontale (hScrollBar), la barra di scorrimento verticale (vScrollBar) e il controllo numerico su/giù (NumericUpDown). | ![]() |
Creiamo la seguente applicazione:
![]() |
N. | Tipo | nome | ruolo |
1 | hScrollBar | hScrollBar1 | una barra di scorrimento orizzontale |
2 | hScrollBar | hScrollBar2 | un cursore orizzontale che segue le modifiche nel cursore 1 |
3 | Casella di testo | txtValue | visualizza il valore del cursore orizzontale ReadOnly=true per impedire qualsiasi immissione |
4 | NumericUpDown | incrementatore | consente di impostare il valore del cursore 2 |
- Un cursore ScrollBar consente all'utente di selezionare un valore da un intervallo di valori interi rappresentati dalla "banda" del cursore, lungo la quale si sposta un cursore. Il valore del cursore è disponibile nella sua proprietà Value.
- Per un cursore orizzontale, l'estremità sinistra rappresenta il valore minimo dell'intervallo, l'estremità destra il valore massimo e il cursore il valore attualmente selezionato. Per un cursore verticale, il minimo è rappresentato dall'estremità superiore e il massimo dall'estremità inferiore. Questi valori sono rappresentati dalle proprietà Minimum e Maximum e hanno come valori predefiniti 0 e 100.
- Facendo clic sulle estremità del cursore, il valore viene modificato di un incremento (positivo o negativo) in base all'estremità su cui si è fatto clic, denominato SmallChange, il cui valore predefinito è 1.
- Facendo clic su uno dei due lati del cursore, il valore cambia di un incremento (positivo o negativo) a seconda dell'estremità su cui si fa clic, un'impostazione denominata LargeChange, il cui valore predefinito è 10.
- Quando si fa clic sull'estremità superiore di un cursore verticale, il suo valore diminuisce. Ciò potrebbe sorprendere l'utente medio, che normalmente si aspetta di vedere il valore "aumentare". È possibile risolvere questo problema impostando le proprietà SmallChange e LargeChange su valori negativi
- Queste cinque proprietà (Value, Minimum, Maximum, SmallChange, LargeChange) sono accessibili sia in lettura che in scrittura.
- L'evento principale del cursore è quello che segnala una variazione di valore: l'evento Scroll.
Un componente NumericUpDown è simile a un cursore: dispone anch'esso delle proprietà Minimum, Maximum e Value, con valori predefiniti rispettivamente pari a 0, 100 e 0. Tuttavia, in questo caso, la proprietà Value viene visualizzata in una casella di immissione che è parte integrante del controllo. L'utente può modificare autonomamente questo valore a meno che la proprietà ReadOnly del controllo non sia stata impostata su true. Il valore di incremento è impostato 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 rilevante per la nostra applicazione è il seguente:
Il modulo viene formattato durante la sua creazione:
' manufacturer
Public Sub New()
' initial form creation
InitializeComponent()
' drive 2 is given the same characteristics as drive 1
hScrollBar2.Minimum = hScrollBar1.Value
hScrollBar2.Minimum = hScrollBar1.Minimum
hScrollBar2.Maximum = hScrollBar1.Maximum
hScrollBar2.LargeChange = hScrollBar1.LargeChange
hScrollBar2.SmallChange = hScrollBar1.SmallChange
' ditto for the incrementer
incrémenteur.Minimum = hScrollBar1.Value
incrémenteur.Minimum = hScrollBar1.Minimum
incrémenteur.Maximum = hScrollBar1.Maximum
incrémenteur.Increment = hScrollBar1.SmallChange
' give TextBox the value of drive 1
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Il gestore che tiene traccia delle modifiche al valore del cursore 1:
' hscrollbar1 drive management
Private Sub hScrollBar1_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar1.Scroll
' value change on drive 1
' its value is passed on to drive 2 and the TxtValeur textbox
hScrollBar2.Value = hScrollBar1.Value
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Il gestore che tiene traccia delle modifiche al valore del cursore 2:
' hscrollbar2 drive management
Private Sub hScrollBar2_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar2.Scroll
' inhibits all changes to drive 2
' forcing it to keep the value of drive 1
e.NewValue = hScrollBar1.Value
End Sub
L'handler che tiene traccia delle modifiche nella barra di scorrimento:
' incremental management
Private Sub incrémenteur_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles incrémenteur.ValueChanged
' set the value of controller 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, ad esempio per visualizzare un punto quando si fa clic. I movimenti del mouse attivano eventi nel contenitore all'interno del quale il mouse si sta muovendo.
![]() | ![]() |
Il mouse è appena entrato nell'area del controllo | |
Il mouse ha appena lasciato l'area del controllo | |
Il mouse si sta spostando all'interno dell'area del controllo | |
Tasto sinistro del mouse premuto | |
Rilascio del pulsante sinistro del mouse | |
L'utente rilascia un oggetto sul controllo | |
L'utente entra nell'area del controllo mentre trascina un oggetto | |
L'utente esce dall'area del controllo mentre trascina un oggetto | |
L'utente si sposta sull'area del controllo mentre trascina un oggetto |
Ecco un programma che ti aiuterà a comprendere meglio quando si verificano i vari eventi del mouse:
![]() |
N. | tipo | nome | ruolo |
1 | Etichetta | lblPosizione | per visualizzare la posizione del mouse nel modulo 1, nell'elenco 2 o nel pulsante 3 |
2 | Casella di riepilogo | lstEvts | per visualizzare eventi del mouse diversi da MouseMove |
3 | Pulsante | btnClear | per cancellare il contenuto di 2 |
I gestori di eventi sono i seguenti. Per tracciare i movimenti del mouse sui tre controlli, scriviamo un unico gestore:
' évt 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
' mvt mouse - displays its (X,Y) coordinates
lblPosition.Text = "(" & e.X & "," & e.Y & ")"
End Sub
È importante notare che ogni volta che il mouse entra nell'area di un controllo, il suo sistema di coordinate cambia. La sua origine (0,0) è l'angolo in alto a sinistra del controllo su cui si trova attualmente. Pertanto, durante l'esecuzione, quando si sposta il mouse dal modulo al pulsante, il cambiamento delle coordinate è chiaramente visibile. Per vedere meglio questi cambiamenti nell'ambito del mouse, è possibile utilizzare la proprietà Cursor dei controlli:

Questa proprietà consente di impostare la forma del cursore del mouse quando entra nell'area del controllo. Pertanto, nel nostro esempio, abbiamo impostato il cursore su Default per il modulo stesso, su Mano per Lista 2 e su No per Pulsante 3, come mostrato nelle schermate sottostanti.



Nel metodo [InitializeComponent], il codice generato da queste scelte è 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, gestiamo gli eventi MouseEnter e MouseLeave per quell'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
' evt 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
' poster
Private Sub affiche(ByVal message As String)
' the message is displayed at the top of the event list
lstEvts.Items.Insert(0, message)
End Sub

Per gestire i clic sul modulo, gestiamo gli eventi MouseDown e MouseUp:
' évt 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
' évt 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 per il gestore dell'evento Click sul pulsante Elimina:
' évt btnEffacer_Click
Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' clears the event list
lstEvts.Items.Clear()
End Sub
5.6. Creazione di una finestra con un menu
Ora vediamo come creare una finestra con un menu. Creeremo la seguente finestra:
![]() |
Il controllo 1 è una casella di testo di sola lettura (ReadOnly=true) denominata txtStatut. L'albero del menu è il seguente:
![]() | ![]() |
Le opzioni di menu sono controlli proprio come gli altri componenti visivi e dispongono di proprietà ed eventi. Ad esempio, la tabella delle proprietà per l'opzione di menu A1:

Nel nostro esempio vengono utilizzate due proprietà:
il nome del controllo menu | |
l'etichetta dell'opzione di menu |
Le proprietà delle varie opzioni di menu nel 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" dalla barra "ToolBox":

Verrà quindi visualizzato un menu vuoto sul modulo con caselle vuote contrassegnate dalla dicitura "Digita qui". È sufficiente inserire lì le varie opzioni del menu:

Per inserire un separatore tra due opzioni, come mostrato sopra tra le opzioni B1 e B2, posiziona il cursore nel punto in cui desideri che appaia il separatore nel menu, fai clic con il tasto destro del mouse e seleziona l'opzione Inserisci separatore:

Se si esegue l'applicazione utilizzando Ctrl+F5, verrà visualizzato un modulo con un menu che non fa ancora nulla. Le opzioni di menu sono trattate come componenti: hanno proprietà ed eventi. Nella [finestra del codice], selezionare il componente mnuA1, quindi selezionare gli eventi associati:

Se si attiva l'evento Click sopra indicato, 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 del menu. In questo caso, la stessa procedura può essere utilizzata per tutte le opzioni. Quindi rinominiamo la procedura precedente *in display* 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
' displays the name of the selected submenu in the TextBox
txtStatut.Text = (CType(sender, MenuItem)).Text
End Sub
In questo metodo, visualizziamo semplicemente la proprietà Text dell'opzione di menu che ha attivato l'evento. Il mittente dell'evento è di tipo Object. Le opzioni di menu sono di tipo MenuItem, quindi in questo caso dobbiamo eseguire il cast da Object a MenuItem. Eseguire l'applicazione e selezionare l'opzione A1 per visualizzare il seguente messaggio:

Il codice rilevante per questa applicazione, oltre al metodo Display, è il codice per la creazione del menu nel costruttore del form (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
Si noti l'istruzione che associa il menu al modulo:
Me.Menu = Me.mainMenu1
5.7. Componenti non visibili
Esamineremo ora una serie di componenti non visibili: questi vengono utilizzati durante la 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 | Casella di testo multilinea | txtText | testo digitato dall'utente o caricato da un file |
2 | Pulsante | btnSave | salva il testo di 1 in un file di testo |
3 | Pulsante | btnLoad | consente di caricare il contenuto di un file di testo in 1 |
4 | Pulsante | btnClear | cancella il contenuto di 1 |
Vengono utilizzati due controlli non visivi:

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

Il codice per il pulsante Clear è semplice:
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' clear the input box
txtTexte.Text = ""
End Sub
La classe SaveFileDialog è definita come segue:

Eredita da diversi livelli di classi. Tra le sue numerose proprietà e metodi, ci concentreremo sui seguenti:
i tipi di file disponibili nell'elenco a discesa dei tipi di file della finestra di dialogo | |
l'indice del tipo di file visualizzato per impostazione predefinita nell'elenco sopra. Inizia da 0. | |
la cartella visualizzata inizialmente 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 DialogResult. |
Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:
![]() |
elenco a discesa generato dalla proprietà Filter. Il tipo di file predefinito è determinato da FilterIndex | |
directory corrente, impostata da InitialDirectory se questa proprietà è stata specificata | |
il nome del file selezionato o digitato direttamente dall'utente. Sarà disponibile nella proprietà FileName | |
Pulsanti Salva/Annulla. Se si utilizza il pulsante Salva, 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
' save the input box in a text file
' set the savefileDialog1 dialog box
saveFileDialog1.InitialDirectory = Application.ExecutablePath
saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
saveFileDialog1.FilterIndex = 0
' display the dialog box and retrieve the result
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
' retrieve the file name
Dim nomFichier As String = saveFileDialog1.FileName
Dim fichier As StreamWriter = Nothing
Try
' open the file for writing
fichier = New StreamWriter(nomFichier)
' we write the text inside
fichier.Write(txtTexte.Text)
Catch ex As Exception
' problem
MessageBox.Show("Problème à l'écriture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' close the file
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Impostiamo la directory iniziale sulla directory contenente il file eseguibile dell'applicazione:
- Impostiamo i tipi di file da visualizzare
Si noti la sintassi del filtro: filtro1|filtro2|..|filtro, dove filtro = Testo|tipo di file. In questo caso, l'utente può scegliere tra file *.txt e *.*.
- Impostiamo il tipo di file da visualizzare all'inizio
In questo caso, all'utente verranno visualizzati per primi i file di tipo *.txt.
- 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 (una cosiddetta finestra di dialogo modale). L'utente imposta il nome del file da salvare ed esce dalla finestra di dialogo cliccando sul pulsante Salva, sul pulsante Annulla o chiudendo la finestra di dialogo. Il risultato del metodo ShowDialog è DialogResult.OK solo se l'utente ha utilizzato il pulsante Salva per uscire dalla finestra di dialogo.
- Una volta fatto ciò, il nome del file da creare si trova ora nella proprietà FileName dell'oggetto saveFileDialog1. Si ritorna quindi al processo standard di creazione di un file di testo. Si scrive il contenuto della TextBox: txtTexte.Text, gestendo eventuali eccezioni che potrebbero verificarsi.
La classe OpenFileDialog è molto simile alla classe SaveFileDialog e deriva dalla stessa discendenza di classi. Tra queste proprietà e metodi, ci concentreremo sui seguenti:
i tipi di file disponibili nell'elenco a discesa dei tipi di file della finestra di dialogo | |
l'indice del tipo di file visualizzato per impostazione predefinita nell'elenco sopra. Inizia da 0. | |
la directory inizialmente visualizzata per la ricerca del file da aprire | |
Il nome del file da aprire, come specificato dall'utente | |
Metodo che visualizza la finestra di dialogo di salvataggio. Restituisce un DialogResult. |
Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:
![]() |
elenco a discesa generato dalla proprietà Filter. Il tipo di file predefinito è determinato da FilterIndex | |
cartella corrente, impostata da InitialDirectory se questa proprietà è stata specificata | |
Nome del file selezionato o digitato direttamente dall'utente. Sarà disponibile nella proprietà FileName | |
Pulsanti Apri/Annulla. Se si utilizza il pulsante Apri, la funzione ShowDialog restituisce il risultato DialogResult.OK |
La procedura aperta può essere scritta come segue:
Private Sub btnCharger_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCharger.Click
' load a text file into the input box
' set the openfileDialog1 dialog box
openFileDialog1.InitialDirectory = Application.ExecutablePath
openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
openFileDialog1.FilterIndex = 0
' display the dialog box and retrieve the result
If openFileDialog1.ShowDialog() = DialogResult.OK Then
' retrieve the file name
Dim nomFichier As String = openFileDialog1.FileName
Dim fichier As StreamReader = Nothing
Try
' open the file in read mode
fichier = New StreamReader(nomFichier)
' read the entire file and put it in the TextBox
txtTexte.Text = fichier.ReadToEnd()
Catch ex As Exception
' problem
MessageBox.Show("Problème à la lecture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' close the file
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Impostiamo la directory iniziale sulla directory contenente l'eseguibile dell'applicazione:
- Impostiamo i tipi di file da visualizzare
- Imposta il tipo di file da visualizzare per primo
In questo caso, i file *.txt verranno visualizzati per primi all'utente.
- Viene visualizzata la finestra di dialogo e ne viene recuperato il risultato
If openFileDialog1.ShowDialog() = DialogResult.OK Then
Mentre la finestra di dialogo è visualizzata, l'utente non ha più accesso al modulo principale (una cosiddetta finestra di dialogo modale). L'utente specifica il nome del file da aprire ed esce dalla finestra di dialogo cliccando sul pulsante Apri, sul pulsante Annulla o chiudendo la finestra di dialogo. Il risultato del metodo ShowDialog è DialogResult.OK solo se l'utente ha utilizzato il pulsante Apri per uscire dalla finestra di dialogo.
- Una volta fatto ciò, il nome del file da creare si trova ora nella proprietà FileName dell'oggetto openFileDialog1. Si ritorna quindi al processo standard di lettura di un file di testo. Si noti il metodo che consente di leggere l'intero file:
- Il contenuto del file viene inserito nella casella di testo txtTexte. Gestiamo eventuali eccezioni che potrebbero verificarsi.
5.7.2. Finestre di dialogo FontColor e ColorDialog
Continuiamo l'esempio precedente introducendo due nuovi pulsanti:
![]() |
No. | tipo | nome | ruolo |
6 | Pulsante | btnColor | per impostare il colore del testo della casella di testo |
7 | Pulsante | btnFont | per impostare il carattere della casella di testo |
Inseriamo un controllo ColorDialog e un controllo FontDialog nel modulo:

Le classi FontDialog e ColorDialog dispongono di un metodo ShowDialog simile 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 utilizzando il pulsante OK, il risultato del metodo ShowDialog è DialogResult.OK e il colore selezionato viene memorizzato nella proprietà Color dell'oggetto ColorDialog utilizzato. Il metodo ShowDialog della classe FontDialog consente di selezionare un tipo di carattere:

Se l'utente chiude la finestra di dialogo facendo clic sul pulsante OK, il risultato del metodo ShowDialog è DialogResult.OK e il font selezionato viene memorizzato nella proprietà Font dell'oggetto FontDialog utilizzato. Abbiamo gli elementi per gestire i clic sui pulsanti Color e Font:
Private Sub btnCouleur_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCouleur.Click
' choice of text color
If colorDialog1.ShowDialog() = DialogResult.OK Then
' change the forecolor property of 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
' font selection
If fontDialog1.ShowDialog() = DialogResult.OK Then
' change the font property of TextBox
txtTexte.Font = fontDialog1.Font
End If
End Sub
5.7.3. Timer
Qui proponiamo di scrivere la seguente applicazione:
![]() |
N. | Tipo | Nome | Ruolo |
1 | Casella di testo, ReadOnly=true | txtChrono | visualizza un timer |
2 | Pulsante | btnStopStart | Pulsante di arresto/avvio per il cronometro |
3 | Timer | timer1 | componente che attiva un evento ogni secondo |
Il timer è in funzione:

Il timer si è fermato:

Per aggiornare il contenuto della casella di testo txtChrono ogni secondo, abbiamo bisogno di un componente che generi un evento ogni secondo, che possiamo intercettare per aggiornare la visualizzazione del cronometro. Questo componente è il Timer:

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

Tra le sue proprietà, prenderemo in considerazione solo le seguenti:
numero di millisecondi dopo i quali viene attivato un evento Tick. | |
l'evento attivato al termine dell'Intervallo in millisecondi | |
imposta il timer su attivo (vero) o inattivo (falso) |
Nel nostro esempio, il timer si chiama timer1 e timer1.Interval è impostato su 1000 ms (1 s). L'evento Tick si verificherà quindi ogni secondo. Un clic sul pulsante Start/Stop viene gestito dalla seguente procedura:
Private Sub btnArretMarche_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnArretMarche.Click
' off or on?
If btnArretMarche.Text = "Marche" Then
' we note the start time
début = DateTime.Now
' we display it
txtChrono.Text = "00:00:00"
' start timer
timer1.Enabled = True
' change the button label
btnArretMarche.Text = "Arrêt"
' end
Return
End If '
If btnArretMarche.Text = "Arrêt" Then
' timer off
timer1.Enabled = False
' change the button label
btnArretMarche.Text = "Marche"
' end
Return
End If
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' a second has passed
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
L'etichetta del pulsante Start/Stop è "Stop" o "Start". Dobbiamo quindi controllare questa etichetta per determinare cosa fare.
- Se l'etichetta è "Start", memorizziamo l'ora di inizio in una variabile globale dell'oggetto form, il timer viene avviato (Enabled=true) e l'etichetta del pulsante cambia in "Stop".
- Se l'etichetta è "Stop", il timer viene arrestato (Enabled=false) e l'etichetta del pulsante viene modificata in "Start".
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
' instance variables
Private début As DateTime
L'attributo start sopra indicato è noto in tutti i metodi della classe. Dobbiamo ancora gestire l'evento Tick sull'oggetto timer1, un evento che si verifica ogni secondo:
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' a second has passed
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
Calcoliamo il tempo trascorso dall'avvio del cronometro. Otteniamo un oggetto TimeSpan che rappresenta una durata. Questo deve essere visualizzato nel timer nel formato hh:mm:ss. Per farlo, utilizziamo le proprietà Hours, Minutes e Seconds dell'oggetto TimeSpan, che rappresentano rispettivamente le ore, i minuti e i secondi della durata. Le visualizziamo utilizzando il formato ToString("d2") per garantire una visualizzazione a due cifre.
5.8. Esempio di calcolo delle imposte
Torniamo all'applicazione IMPOTS, che abbiamo già trattato due volte. Ora aggiungiamo un'interfaccia utente grafica:
![]() |
I controlli sono i seguenti
N. | Tipo | nome | ruolo |
Pulsante di opzione | rdYes | selezionato se sposato | |
Pulsante di opzione | rdNo | Selezionato se non sposato | |
NumericUpDown | incChildren | numero dei figli del contribuente Minimo=0, Massimo=20, Incremento=1 | |
Casella di testo | txtSalario | stipendio annuale del contribuente in F | |
Casella di testo | txtTaxes | importo delle imposte dovute ReadOnly=true | |
Pulsante | btnCalcola | avvia il calcolo delle imposte | |
Pulsante | btnClear | ripristina il modulo allo stato iniziale al momento del caricamento | |
Pulsante | btnExit | per uscire dall'applicazione |
Regole di funzionamento
- Il pulsante Calcola rimane disabilitato finché il campo dello stipendio è vuoto
- Se, al momento del calcolo, lo stipendio risulta errato, viene segnalato un errore:

Il programma è riportato di seguito. Utilizza la classe Impot creata nel capitolo dedicato alle classi. Parte del codice generato automaticamente da VS.NET non è stato riprodotto qui.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
' options
Option Explicit On
Option Strict On
' namespaces
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
' form class
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
' data tables required for tax calculation
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}
' tax object
Private objImpôt As impot = Nothing
Public Sub New()
InitializeComponent()
' form initialization
btnEffacer_Click(Nothing, Nothing)
btnCalculer.Enabled = False
' tax object creation
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)
' inhibit the salary entry field
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
' raz du formulaire
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
' calculate button status
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
' end application
Application.Exit()
End Sub 'btnQuitter_Click
Private Sub btnCalculer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCalculer.Click
' is the salary correct?
Dim intSalaire As Integer = 0
Try
' salary recovery
intSalaire = Integer.Parse(txtSalaire.Text)
' it must be >=0
If intSalaire < 0 Then
Throw New Exception("")
End If
Catch ex As Exception
' error msg
MessageBox.Show(Me, "Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error)
' focus on wrong field
txtSalaire.Focus()
' select text for input field
txtSalaire.SelectAll()
' back to visual interface
Return
End Try 'try-catch
' salary is correct - tax is calculated
txtImpots.Text = "" & CLng(objImpôt.calculer(rdOui.Checked, CInt(incEnfants.Value), intSalaire))
End Sub 'btnCalculer_Click
End Class
Qui utilizziamo l'assembly impots.dll, che è il risultato della compilazione della classe impots del Capitolo 2. Ricordiamo che questo assembly può essere generato in modalità console utilizzando il comando
Questo comando genera il file impots.dll, noto come assembly. Questo assembly può quindi essere utilizzato in vari progetti. Qui, nel nostro progetto in VS.NET, utilizziamo la finestra delle proprietà del progetto:

Per aggiungere un riferimento (un assembly), facciamo clic con il tasto destro del mouse sul gruppo Riferimenti in alto, selezioniamo l'opzione [Aggiungi riferimento] e specifichiamo l'assembly [impots.dll] che abbiamo inserito 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 che l'assembly [impots.dll] è incluso 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. Per farlo, nella finestra delle proprietà del progetto, fare clic con il tasto destro del mouse sul progetto, selezionare l'opzione [Aggiungi/Aggiungi elemento esistente] e specificare il file impots.vb.















































