Connessione al database con Visual Basic NET? Lo trovi su Opentraining.it Visual Basic Italia
PRINCIPALE > CORSO DI VISUAL BASIC

Eseguire una ricerca veloce nell' archivio delle risorse di Visual Basic Italia®: 

Preso dall'archivio...

Premere il pulsante sotto per accedere direttamente ad un articolo o ad un esempio preso in modo casuale dall'archivio.



Ultimo e-book pubblicato:

"INTRODUZIONE AI CSS"

Lo scopo del CSS language è quello di controllare lo stile dei vari elementi che concorrono a formare un
documento HTML.
Si può operare in tre modi collegamento ad un foglio di stile esterno;definizione degli stili all'inizio
del documento utilizzo della proprietà style all'interno di un Tag HTML (embedded style). Questo e-book introduttivo
servirà per apprendere tali nozioni fondametali dei fogli di stile.

Prezzo: € 0.0.
Presentazione:
REAL SOFTWARE RILASCIA LA VERSIONE 5.0 di REALbasic per Windows






Gorizia, 5 maggio 2003 - Active, distributore in esclusiva di REALSoftware, Austin, Tx, annuncia la disponibilità di REALbasic 5.0 per Windows, uno strumento per lo sviluppo semplice da usare che permette agli utenti Windows di tutti i livelli di creare applicazioni personalizzate e di compilarle sia per la piattaforma Windows che per quella Macintosh.
[>>]

http://www.active-software.com

 

Contatti. Utilizzare l'email generica per domande relative al sito:
Porre domande relative al sito
oppure scrivere ad un responsabile di area.
Responsabile del sito: >Andrea Martelli
Responsabile area "Corso di VB":
> Giorgio Abraini

Corso di Visual Basic: lezione 31

Questa lezione, consultata da 23181 utenti, è stata giudicata di ottimi contenuti , con un'esposizione perfettamente comprensibile e con un livello di approfondimento ottimo da 66 votanti.


Lezione 31

Nella lezione precedente abbiamo visto come correggere alcuni bug presenti nella prima versione del nostro "Campo Minato": ora vediamo come migliorare ulteriormente l'applicazione costruendo un controllo personalizzato che abbia le funzioni delle "mine". Visual Basic infatti dà la possibilità al programmatore di creare un controllo (come potrebbe essere ad es. il textbox o la label) che abbia caratteristiche definite dallo stesso programmatore in modo da poterlo adattare alle sue esigenze; tali controlli sono denominati "controlli ActiveX" perché sfruttano la tecnologia ActiveX creata da Microsoft per estendere la precedente tecnologia OLE; oltre ai controlli, esistono anche i server ActiveX e i documenti ActiveX. Questa tecnologia permette una maggiore integrazione con internet ed è sfruttabile da tutti i linguaggi di programmazione che la supportano, così che un controllo ActiveX creato con Visual Basic può essere utilizzato ad es. anche tramite il Visual C++ o il Borland Delphi.
Quando si crea un controllo ActiveX in effetti si definisce la classe del controllo, classe che sarà poi istanziata una o più volte dalle applicazioni client che conterranno quel controllo; la classe è definita in un file *.ctl, che viene compilato in un file *.ocx. Una volta creato il controllo, lo sviluppatore che lo utilizza può collocarlo su un form come qualsiasi altro controllo, creando così un'istanza di progettazione del controllo; essa può essere programmata tramite l'interfaccia esposta dal controllo: ad es. il programmatore può inserire codice negli eventi (se ce ne sono) generati dal controllo, e può usarne i metodi e le proprietà. Quando invece l'applicazione client viene eseguita, viene generata un'istanza di esecuzione del controllo, la quale esegue il codice incapsulato in esso e interagisce col suo contenitore (tipicamente un form) e con gli altri controlli eventualmente presenti.
Per creare un controllo ActiveX occorre selezionare "Controllo ActiveX" dalla finestra di apertura di un nuovo progetto:

Visual Basic creerà una finestra di progettazione del tutto analoga a quella di un form; essa rappresenta l'oggetto UserControl, che è la base su cui viene costruito ogni controllo personalizzato. All'interno dello UserControl, come in un form, è possibile collocare i controlli costitutivi del componente ActiveX; ogni istanza del componente, pertanto, conterrà un'istanza dell'oggetto UserControl e dei vari controlli disposti al suo interno, così come quando al caricamento di un form durante l'esecuzione di un'applicazione vengono generate istanze di tutti i controlli presenti nel form. L'oggetto UserControl fornisce l'interfaccia per far interagire il controllo ActiveX con i suoi controlli costitutivi eventualmente in risposta ad azioni dell'utente: ad es. fornisce gli eventi generati dal mouse o dalla tastiera, gli eventi di inizializzazione e terminazione del controllo, ecc.
L'interazione con il contenitore del controllo è però supportata dall'oggetto Extender, che fornisce alcune proprietà di estensione, cioè le caratteristiche dell'interfaccia del componente ActiveX controllate dal suo contenitore.
Ad es. un controllo ActiveX non può sapere a priori quale sarà il contenitore nel quale sarà collocato, per cui una proprietà come Parent, che appunto identifica il contenitore del controllo, non può essere gestita dal controllo stesso ma deve essere gestita dal suo contenitore: ciò avviene tramite l'oggetto Extender, accessibile tramite l'apposita proprietà dell'oggetto UserControl. Lo stesso dicasi per proprietà come Left o Top, che indicano la posizione del controllo all'interno del contenitore: è intuibile che dev'essere il contenitore a gestirle, e anche questo avviene tramite l'oggetto Extender.

L'utilizzatore del controllo non si accorge della differenza, perché per lui tutte queste proprietà sono fornite dal controllo ActiveX; invece lo sviluppatore del controllo deve fare un po' più attenzione. Infatti, secondo le specifiche ActiveX definite da Microsoft ogni oggetto Extender dovrebbe fornire almeno le proprietà Cancel, Default, Name, Parent e Visible, ma può darsi che un determinato contenitore non gestisca queste proprietà o altre non standard, come ad es. Index, o Left o Enabled. In tal caso, se si tenta di accedere a una proprietà di estensione non supportata dal contenitore, si verificherà un errore (più precisamente l'errore 438: "L'oggetto non supporta la proprietà o il metodo"): pertanto è opportuno che lo sviluppatore del controllo usi codice di intercettazione degli errori quando tenta di accedere a proprietà di estensione. Inoltre, proprio perché l'oggetto Extender dipende dal contenitore, esso diventa disponibile solo quando il controllo è stato effettivamente collocato nel contenitore, ovvero quando è stata creata un'istanza del controllo; in altre parole, l'oggetto Extender non è disponibile nell'evento Initialize dell'oggetto UserControl. Naturalmente Visual Basic fornisce per ogni oggetto Extender non solo le proprietà standard indicate sopra ma anche altre (ad es. Tag, TabStop, TooltipText) insieme ad alcuni metodi ed eventi (ad es. il metodo SetFocus o l'evento GetFocus).
Altre importanti proprietà per una corretta interazione del controllo con il contenitore sono fornite dall'oggetto AmbientProperties, accessibile tramite la proprietà Ambient dell'oggetto UserControl: queste proprietà di ambiente definiscono alcune caratteristiche dell'ambiente in cui si trova il controllo ActiveX, ad es. le proprietà BackColor e ForeColor suggeriscono colori di sfondo e di primo piano per fare in modo che il controllo ActiveX si presenti in modo uniforme con il suo contenitore. In particolare, occorre prestare attenzione alla proprietà DisplayName, che restituisce il nome dell'istanza del controllo (differisce dalla proprietà UserControl.Name perché quest'ultima definisce il nome del controllo e non della sua particolare istanza), e alla proprietà UserMode, che indica se ci si trova in fase di esecuzione (UserMode=True) o di progettazione (UserMode=False).
Se ci si trova in fase di progettazione, significa che l'istanza non è in modalità "utente" (per utente si intende qui l'utilizzatore finale del controllo, ovvero chi usa l'applicazione) e quindi la proprietà UserMode è False. Tale proprietà risulta molto utile quando certe porzioni di codice vanno eseguite solo in fase di esecuzione: infatti, anche se a prima vista può sembrare strano, il codice di un controllo ActiveX può essere eseguito anche in fase di progettazione. Alcuni esempi chiariranno le nozioni fin qui esposte.

Dato che il controllo ActiveX che stiamo per costruire sarà da utilizzare nel campo minato, apriamo il progetto relativo al gioco e aggiungiamo un nuovo progetto scegliendo "Controllo ActiveX":


Visual Basic creerà un "gruppo" di progetti visibile nella finestra "gestione progetti", in cui l'originario Campo Minato apparirà in grassetto perché è il progetto di avvio (ovvero quello che viene avviato quando si preme F5); è possibile impostare un progetto come progetto di avvio cliccando col tasto destro del mouse sulla voce del progetto e selezionando l'apposita voce dal menù di contesto. Il progetto relativo al controllo ActiveX è identificato (oltre che dall'icona) da un oggetto UserControl a cui corrisponde un file *.ctl; possiamo dare "Mina" come nome dell'oggetto, visto che il controllo serve appunto a creare una mina personalizzata: questo sarà il nome della classe (come "TextBox"), poi ogni istanza dell'oggetto avrà il suo nome particolare, ad es. Mina1, Mina2 (come TextBox1, TextBox2) ecc.
Poiché la mina è costituita essenzialmente da un pulsante, all'interno della finestra di progettazione dello UserControl inseriamo, come se si trattasse di un form, un CommandButton; questo pulsante, che rappresenta un controllo (in questo caso IL controllo) costitutivo del controllo ActiveX, dovrà avere un nome appropriato, ad es. "cmdMina". Aprendo l'editor del codice relativo alla classe Mina.ctl vi accorgerete che sono elencati due oggetti: cmdMina e UserControl, ciascuno con i suoi eventi.


Nella casella degli strumenti, inoltre, è stata aggiunta automaticamente un'icona che rappresenta il nostro controllo ActiveX;


proviamo a inserire il nostro controllo Mina all'interno della finestra del Campo Minato come faremmo con un qualunque altro controllo (se l'icona dell'ActiveX risulta disabilitata è perché la finestra di progettazione dello UserControl è ancora aperta: chiudetela).
Ora, quasi certamente non vi sarete preoccupati della posizione del pulsante cmdMina all'interno dello UserControl, cosicché disegnando il controllo Mina all'interno del form del Campo Minato avete ottenuto un risultato diciamo insoddisfacente; poco importa, basta ridimensionare il pulsante sfruttando l'evento Resize.
Quando il controllo Mina è stato inserito nel form, è stata creata un'istanza di progettazione del controllo, con un'istanza sia dell'oggetto UserControl, sia dell'oggetto cmdMina: pertanto quando la Mina è collocata sul form saranno generati gli eventi di inizializzazione del controllo e anche l'evento Resize; se all'interno di questo evento scriviamo il seguente codice:

With cmdMina
.Left = 0
.Top = 0
.Height = UserControl.Height
.Width = UserControl.Width
End With

vedremo che all'inserimento della Mina sul form il pulsante cmdMina avrà esattamente le dimensioni che vogliamo dargli noi disegnando il controllo sul form, perché è il controllo stesso che obbliga cmdMina ad avere quelle dimensioni in occasione dell'evento Resize.
Questa è anche la dimostrazione del fatto, cui accennavo prima, che il codice di un controllo ActiveX è eseguito anche in fase di progettazione, oltre che a run-time. Ora, poiché di norma non è possibile ridimensionare i controlli in fase di esecuzione, dovremmo assicurarci che il codice dell'evento Resize venga eseguito solo in fase di progettazione: a questo scopo torna utile la proprietà UserMode descritta sopra:

If Not UserControl.Ambient.UserMode Then
With cmdMina
.Left = 0
.Top = 0
.Height = UserControl.Height
.Width = UserControl.Width
End With
End If

Il pulsante cmdMina viene ridimensionato solo se UserMode è falso, ovvero solo se siamo in fase di progettazione; questo però sarebbe un errore, perché in realtà il ridimensionamento avviene non solo quando viene creata un'istanza di progettazione del controllo, ma anche quando viene creata un'istanza di esecuzione: perciò è meglio togliere la condizione If (potete rendervi conto voi stessi della differenza eseguendo il progetto con e senza la condizione). Ora, avrete notato che all'istanza di progettazione del controllo Mina è stato assegnato per default il nome "Mina1" da Visual Basic: controllando gli eventi associati all'oggetto Mina1 noterete anche che manca l'evento Resize, che invece esiste per quasi tutti i controlli standard.
Questo avviene perchè l'interfaccia dello UserControl (come anche del pulsante cmdMina) è incapsulata all'interno del controllo ActiveX e quindi non visibile di per sé all'utente che utilizza il controllo; gli eventi, le proprietà e i metodi dell'oggetto Mina disponibili per default sono solo quelli provvisti dall'oggetto Extender, e li potete vedere utilizzando il visualizzatore oggetti (facendo attenzione che il progetto attivo sia quello del campo minato e non quello del controllo ActiveX) e selezionando l'oggetto "Mina". Mancano le proprietà Cancel e Default, che pure fanno parte delle proprietà standard che ogni oggetto Extender dovrebbe fornire, semplicemente perché il nostro controllo ActiveX non è configurato per essere un pulsante di comando, per cui quelle proprietà non avrebbero senso; infatti la proprietà DefaultCancel dello UserControl è per default impostata su False.
Per rendere visibile anche all'utente l'evento Resize (o altri elementi dell'interfaccia) dello UserControl, occorre dichiarare un apposito evento Resize che faccia da delegato per lo stesso evento del controllo ActiveX: la delega è il meccanismo che consente di esporre l'interfaccia dello UserControl o dei controlli costitutivi all'utilizzatore del controllo ActiveX. Il fatto che queste interfacce non siano automaticamente disponibili all'utente può sembrare una seccatura per lo sviluppatore del controllo, che deve provvedere a delegare tutte quelle che gli sembra opportuno, ma consente la massima libertà nella creazione dell'interfaccia appropriata che il controllo deve avere per chi lo utilizza. Tornando a noi, dobbiamo quindi dichiarare un evento Resize nella sezione delle dichiarazioni dello UserControl:

Option Explicit

Public Event Resize()

Questo sarà un evento appartenente all'interfaccia del controllo ActiveX Mina e dovrà essere generato dall'evento Resize dell'oggetto UserControl:

Private Sub UserControl_Resize()

With cmdMina
.Left = 0
.Top = 0
.Height = UserControl.Height
.Width = UserControl.Width
End With
RaiseEvent Resize

End Sub

Ora, nel form del Campo Minato, l'oggetto Mina1, istanza del controllo Mina, disporrà anche dell'evento Resize. Volendo evitare di seguire la procedura di delega manualmente per tutti (o quasi) gli elementi dell'interfaccia del controllo ActiveX, è possibile avvalersi della creazione guidata disponibile come aggiunta nell'IDE di Visual Basic.
Come visto nella scorsa lezione, gli eventi che più ci interessano sono MouseDown e Click, unitamente alla proprietà Enabled; questa proprietà non figura inizialmente tra quelle esposte dall'interfaccia del controllo Mina perché, nonostante sia fornita dall'oggetto Extender, è necessario che sia esplicitamente dichiarata come delega dell'omonima proprietà dello UserControl:

Public Property Get Enabled() As Boolean
Enabled = UserControl.Enabled
End Property

Public Property Let Enabled(ByVal vNewValue As Boolean)
UserControl.Enabled = vNewValue
PropertyChanged "Enabled"
End Property

La Property Get non fa altro che esportare il valore corrente della corrispondente proprietà dell'oggetto UserControl, mentre la Property Let, oltre a impostare tale valore secondo quanto specificato dall'utilizzatore del controllo, segnala tramite l'istruzione PropertyChanged che il valore della proprietà è cambiata, in modo che Visual Basic possa memorizzare l'impostazione e assegnarla correttamente alla proprietà quando crea l'istanza di esecuzione. PropertyChanged è un'istruzione che serve in particolar modo in fase di progettazione, affinché Visual Basic aggiorni correttamente le impostazioni delle proprietà per quelle istanze che hanno subito modifiche.
L'implementazione della proprietà Enabled descritta sopra è quella standard, ma a noi serve qualcosa di leggermente diverso: quello che dovremmo abilitare o disabilitare non è tanto il controllo ActiveX Mina ma piuttosto il pulsante cmdMina, perché in ogni caso dobbiamo essere in grado di intercettare almeno il click col tasto destro per issare o ammainare la bandiera sul pulsante.
Tuttavia, l'utilizzatore del componente ActiveX dovrebbe poter comunque disabilitare, se lo desidera, l'intero controllo e non semplicemente i suoi controlli costitutivi. Una soluzione a questo problema è delegare le proprietà Enabled sia dell'oggetto UserControl sia dell'oggetto cmdMina, in modo che l'utilizzatore del controllo possa scegliere liberamente se disattivarlo completamente o soltanto "in parte". Questa soluzione va bene nel nostro caso specifico, ma naturalmente potrebbe non essere adatta a qualunque situazione: lo sviluppatore deve valutare caso per caso se è opportuno esporre membri dell'interfaccia dei controlli costitutivi. Inseriamo quindi la proprietà EnabledCmd:

Public Property Get EnabledCmd() As Boolean
EnabledCmd = cmdMina.Enabled
End Property

Public Property Let EnabledCmd(ByVal vNewValue As Boolean)
cmdMina.Enabled = vNewValue
PropertyChanged "EnabledCmd"
End Property

Inoltre, per la nostra Mina risulta molto utile generare un apposito evento per il click destro, in modo che l'utilizzatore sappia esattamente quando occorre disabilitare solo il cmdMina e non l'intero UserControl; per far ciò dichiariamo due eventi "click":

Option Explicit

Public Event Resize()
Public Event ClickLeft()
Public Event ClickRight()

ClickLeft corrisponde al normale evento Click, ClickRight corrisponde al click col tasto destro che in precedenza avevamo intercettato tramite l'evento MouseDown; ora l'intercettazione non viene più fatta a livello dell'evento generato nell'applicazione Campo Minato, ma direttamente nel controllo ActiveX: in altri termini, non è più l'utilizzatore del controllo a preoccuparsi dell'intercettazione del click destro, ma è il suo sviluppatore, che fornisce direttamente l'evento ClickRight nell'interfaccia del controllo.
L'intercettazione deve avvenire nell'evento MouseDown sia dello UserControl sia di cmdMina, perché quest'ultimo potrebbe essere disattivato anche se lo UserControl è ancora attivo; se il click destro fosse intercettato solo nell'evento MouseDown di cmdMina non avremmo risolto il problema che abbiamo incontrato nella scorsa lezione.
Infatti, se cmdMina è attivo, tutti gli input del mouse andranno su di esso senza generare gli eventi corrispondenti di UserControl: quindi è necessario intercettare l'evento cmdMina_MouseDown; invece se cmdMina è disattivo, gli input del mouse andranno solo sullo UserControl e ovviamente non su cmdMina: perciò è necessario intercettare anche l'evento UserControl_MouseDown:

Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
If Button = vbRightButton Then
RaiseEvent ClickRight
End If
End Sub

Private Sub cmdMina_Click()
RaiseEvent ClickLeft
End Sub

Private Sub cmdMina_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbRightButton Then
RaiseEvent ClickRight
End If
End Sub

Anche l'evento ClickLeft potrebbe essere generato dall'evento cmdMina_MouseDown, a discrezione dello sviluppatore. Ora l'utilizzatore del controllo può scrivere del codice come questo:

Private Sub Mina1_ClickRight()
Mina1.EnabledCmd = Not Mina1.EnabledCmd
End Sub

Cliccando col tasto destro sull'istanza Mina1, l'utilizzatore attiva o disattiva automaticamente il solo cmdMina del controllo ActiveX, lasciando attivo il controllo in se stesso e permettendo così l'intercettazione di un ulteriore click col tasto destro; in questo modo non occorre più "inibire" il click sinistro utilizzando un flag come avevamo fatto nella precedente lezione, perché il click sinistro viene generato solo quando cmdMina è attivato. Inserendo un'istruzione del tipo: Debug.Print "pippo" nell'evento Mina1_ClickLeft, ci si può rendere conto meglio di come funziona il procedimento implementato.