Skip to content

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

dos>vbc /r:system.dll /r:system.drawing.dll /r:system.windows.forms.dll frm1.vb

dos>frm1

L'esecuzione visualizza la seguente finestra:

Image

Un'interfaccia utente grafica deriva generalmente dalla classe base System.Windows.Forms.Form:

Public Class Form1
    Inherits 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:

Public Event Click As EventHandler

dove EventHandler è una funzione "delegata" con la seguente firma:

Public Delegate Sub EventHandler(ByVal sender As Object,ByVal e As EventArgs)

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:

Image

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
   InterrompiRiprovaIgnora
  OK
    OKAnnulla
    RiprovaAnnulla
    SìNo
    SìNoAnnulla

Il parametro icon può assumere valori corrispondenti alle seguenti costanti:

Asterisco
Errore
come sopra Stop
Esclamazione
come Avviso
Mano
Informazioni
come Asterisk
Nessuna
Domanda
Basta
Come la mano
Attenzione

 

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

  1. Avviare VS.NET e selezionare File/Nuovo/Progetto

Image

  1. Specificare le caratteristiche del progetto
    1. Seleziona il tipo di progetto che desideri creare; in questo caso, un progetto VB.NET (1)
    2. Seleziona il tipo di applicazione che desideri creare; in questo caso, un'applicazione Windows (2)
    3. Indica la cartella in cui desideri inserire la sottocartella del progetto (3)
    4. Inserisci il nome del progetto (4). Questo sarà anche il nome della cartella che conterrà i file del progetto
    5. Il nome di questa cartella viene visualizzato in (5)
  1. 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:

Image

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

Image

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):

Image

È possibile accedere a entrambi direttamente dalla finestra "Esplora soluzioni":

 

Le finestre aperte si "impilano" nella finestra di progettazione principale:

Image

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à:

Image

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:

Image

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:

Image

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:

Public Class Form1
    Inherits 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à]:

Image

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

Image

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:

Imports System.Windows.Forms

quindi ricompiliamo:

dos>vbc /r:system.dll /r:system.windows.forms.dll form1.vb

Questa volta funziona. Eseguiamolo:

dos>dir
14/03/2004  11:53               514 Form1.vb
14/03/2004  12:15             3 584 Form1.exe

dos>form1

Image

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:

dos>vbc /r:system.dll /r:system.windows.forms.dll /r:system.drawing.dll /m:form2 form2.vb

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:

Image

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:

Image

La finestra Proprietà apparirà quindi sulla destra:

Image

Vale la pena notare alcune di queste proprietà:

Colore di sfondo
per impostare il colore di sfondo della finestra
ForeColor
per impostare il colore della grafica o del testo nella finestra
Menu
per associare un menu alla finestra
Testo
per assegnare un titolo alla finestra
FormBorderStyle
per impostare il tipo di finestra
Font
per impostare il carattere del testo nella finestra
Nome
per impostare il nome della finestra

Qui impostiamo le proprietà Text e Name:

Testo
Cerniere e bottoni - 1
Nome
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:
  1. seleziona i vari componenti da formattare insieme (tieni premuto il tasto Ctrl)
  2. selezionare l'opzione di formattazione desiderata
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à:
  • Etichetta 1
Selezionare il componente per aprire
per aprire la finestra delle Proprietà. In questa finestra,
modificare le seguenti proprietà:
nome: lblSaisie, testo: Saisie
  • Campo di immissione 2 (TextBox)
Selezionare il componente per aprire la relativa
finestra delle proprietà. In questa finestra, modificare
le seguenti proprietà:
nome: txtSaisie, testo: lasciare vuoto
  • Pulsante 3 (Pulsante):
nome: cmdAfficher, testo: Visualizza
  • la finestra stessa: nome: frmSaisies&Boutons,
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:

Image

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

Image

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:

sender
l'oggetto che ha generato l'evento (in questo caso, il pulsante)
e
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:

Image

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:
Addhandler E, AddressOf P1
Addhandler E, AddressOf P2
...
Addhandler E, AddressOf Pn

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
Chiusura
Il modulo si sta chiudendo
Chiuso
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:

Image

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
ScrollBars=(None, Horizontal, Vertical, Both)
per specificare se il controllo deve avere le barre di scorrimento (Orizzontale, Verticale, Entrambe) o meno (Nessuna)
AcceptReturn=(True, False)
se impostato su true, il tasto Invio passerà alla riga successiva
AcceptTab=(True, False)
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
DropDown
elenco a discesa con casella di modifica
DropDownList
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:

Public ReadOnly Property Items As ComboBox.ObjectCollection

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
C.Items(i)
elemento i del ComboBox
C.Add(object o)
aggiunge l'oggetto o come ultimo elemento della casella combinata
C.AddRange(object() oggetti)
aggiunge un array di oggetti alla fine del menu a discesa
C.Insert(int i, object o)
aggiunge l'oggetto o alla posizione i nel menu a discesa
C.RemoveAt(int i)
rimuove l'elemento i dalla casella combinata
C.Remove(object o)
rimuove l'oggetto o dalla casella combinata
C.Clear()
cancella tutti gli elementi dalla casella combinata
C.IndexOf(oggetto o)
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.

Image

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
MouseLeave
Il mouse ha appena lasciato l'area del controllo
MouseMove
Il mouse si sta spostando all'interno dell'area del controllo
MouseDown
Tasto sinistro del mouse premuto
MouseUp
Rilascio del pulsante sinistro del mouse
Trascinamento
L'utente rilascia un oggetto sul controllo
DragEnter
L'utente entra nell'area del controllo mentre trascina un oggetto
DragLeave
L'utente esce dall'area del controllo mentre trascina un oggetto
DragOver
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:

Image

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.

Image

Image

Image

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

Image

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

Image

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:

Image

Nel nostro esempio vengono utilizzate due proprietà:

 
il nome del controllo menu
Testo
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":

Image

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

Image

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:

Image

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:

Image

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:

Image

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:

Image

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":

Image

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:

Image

Eredita da diversi livelli di classi. Tra le sue numerose proprietà e metodi, ci concentreremo sui seguenti:

string Filter
i tipi di file disponibili nell'elenco a discesa dei tipi di file della finestra di dialogo
int FilterIndex
l'indice del tipo di file visualizzato per impostazione predefinita nell'elenco sopra. Inizia da 0.
Stringa
DirectoryIniziale
la cartella visualizzata inizialmente per il salvataggio del file
stringa FileName
Il nome del file di salvataggio specificato dall'utente
DialogResult.ShowDialog()
Metodo che visualizza la finestra di dialogo di salvataggio. Restituisce un DialogResult.

Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:

1
elenco a discesa generato dalla proprietà Filter. Il tipo di file predefinito è determinato da FilterIndex
2
directory corrente, impostata da InitialDirectory se questa proprietà è stata specificata
3
il nome del file selezionato o digitato direttamente dall'utente. Sarà disponibile nella proprietà FileName
4
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:
        saveFileDialog1.InitialDirectory = Application.ExecutablePath
  • Impostiamo i tipi di file da visualizzare
        saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"

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
        saveFileDialog1.FilterIndex = 0

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:

string Filter
i tipi di file disponibili nell'elenco a discesa dei tipi di file della finestra di dialogo
int FilterIndex
l'indice del tipo di file visualizzato per impostazione predefinita nell'elenco sopra. Inizia da 0.
stringa InitialDirectory
la directory inizialmente visualizzata per la ricerca del file da aprire
stringa FileName
Il nome del file da aprire, come specificato dall'utente
DialogResult.ShowDialog()
Metodo che visualizza la finestra di dialogo di salvataggio. Restituisce un DialogResult.

Il metodo ShowDialog visualizza una finestra di dialogo simile alla seguente:

1
elenco a discesa generato dalla proprietà Filter. Il tipo di file predefinito è determinato da FilterIndex
2
cartella corrente, impostata da InitialDirectory se questa proprietà è stata specificata
3
Nome del file selezionato o digitato direttamente dall'utente. Sarà disponibile nella proprietà FileName
4
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:
            saveFileDialog1.InitialDirectory=Application.ExecutablePath
  • Impostiamo i tipi di file da visualizzare
            saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
  • Imposta il tipo di file da visualizzare per primo
            saveFileDialog1.FilterIndex = 0

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:
                    txtTexte.Text=fichier.ReadToEnd
  • 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:

Image

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:

Image

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:

Image

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:

Image

Il timer si è fermato:

Image

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:

Image

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:

Image

Tra le sue proprietà, prenderemo in considerazione solo le seguenti:

Intervallo
numero di millisecondi dopo i quali viene attivato un evento Tick.
Tick
l'evento attivato al termine dell'Intervallo in millisecondi
Abilitato
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
1
Pulsante di opzione
rdYes
selezionato se sposato
2
Pulsante di opzione
rdNo
Selezionato se non sposato
3
NumericUpDown
incChildren
numero dei figli del contribuente
Minimo=0, Massimo=20, Incremento=1
4
Casella di testo
txtSalario
stipendio annuale del contribuente in F
5
Casella di testo
txtTaxes
importo delle imposte dovute
ReadOnly=true
6
Pulsante
btnCalcola
avvia il calcolo delle imposte
7
Pulsante
btnClear
ripristina il modulo allo stato iniziale al momento del caricamento
8
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:

Image

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

dos>vbc /t:library impots.vb

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:

Image

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.