Traveler 1.0.0
a cura di Emilio Scaccaglia (requisiti: quasi nessuno)

Premessa
Ho sempre pensato che le basi per un buon programmatore siano radicate in una più che ottima conoscenza dei costrutti fondamentali del linguaggio di programmazione.

La conoscenza dei problemi che un software deve risolvere o perlomeno lenire è pure fondamentale per la riuscita del progetto.

Ho notato da qualche anno a questa parte che tutti i testi che parlano di Visual Basic prendono in considerazione quasi esclusivamente i nuovi costrutti introdotti in nell'ultima versione del linguaggio, di cui l'autore del testo vuole parlare, o spiegano accuratamente come disegnare finestre e controlli o (utilissimo) come collegarsi ad una fonte di dati.
Ma le istruzioni fondamentali del linguaggio dove sono finite?

Molti testi, con caratteristiche vicine a quanto sopra scritto, vengono venduti come consigliati ai principianti. Ma se uno non conosce le istruzioni base del linguaggio, come principiante, chi gliele mostra?

Ebbene, ritengo che attualmente non esista nessun testo moderno, che spieghi dettagliatamente l'uso delle istruzioni fondamentali del linguaggio Visual Basic. Istruzioni che sono, nella maggiore parte dei casi, rimaste identiche fin dalla prima versione del linguaggio.

Naturalmente questo mio sfogo rimane tale, dato che queste poche pagine non possono colmare il vuoto sopra descritto. Piuttosto, con esse, vorrei mostrare, a chi se ne voglia servire, come iniziare un semplicissimo progetto, un semplicissimo programma scritto in Visual Basic 2008, partendo dalla prima finestra, fino alla sua distribuzione ad utenti che benevolmente se ne vogliano servire.

Questo, nelle mie intenzioni, è il primo di tre piccoli progetti che vorrei descrivere dettagliatamente, anche se in poche pagine, al fine di portare il lettore, programmatore in erba, ma necessariamente in possesso di alcune conoscenze minime del linguaggio, a comprendere come sia possibile, seguendo il ragionamento logico che sta dietro la realizzazione di un software, riuscire, copiando e modificando progetti già esistenti, a realizzare i primi propri progetti completi.

Progettare Traveler passando da Skipper
Un progetto a cui tengo, in quanto antesignano degli attuali browser quali Firefox e Explorer 7, è quello che circa dieci anni fa chiamai Skipper (colui che guida la navigazione). Progettato, come già detto, circa dieci anni fa, Skipper aveva la caratteristica, oggi comune a tutti i principali browser, di permettere l'apertura contemporanea di più pagine web, all'interno di una unica finestra del programma. Il sistema era veramente semplice, e non comportava particolari conoscenze nel campo della programmazione. Scrissi, a quel tempo, anche un articolo intitolato "Un browser per amico". L'articolo fu pubblicato sulla rivista "Visual Basic Journal" alcuni mesi dopo la realizzazione di tale progetto.

Il progetto realizzato con Microsoft Visual Basic 6.0, Service Pack 4 o Service Pack 5, non ricordo bene, prevedeva l'uso di una finestra MDI, la quale avrebbe contenuto finestre figlie, a loro volta contenenti il controllo Webbrowser. Facile no?

Alcuni pulsanti per muoversi fra le pagine Web (avanti/indietro/home) e un controllo textbox per inserire gli indirizzi URL. Naturalmente bisognava scrivere un po' di codice per unire il tutto, ma questo risultava facile, estremamente facile direi, dato che il controllo webbrowser aveva (ed ha tutt'ora) tutto quello che serve per realizzare con poche linee di codice, un browser ex novo.

Non volevo cambiare molto del progetto originale, ma avevo bisogno di riprogrammare Skipper come esempio per uno dei miei corsi di informatica. Il passaggio di Skipper da VB6 a VB2005 versione Express non poteva avvenire per mezzo di uno strumento automatico di traduzione, in primo luogo perché volevo controllare personalmente il codice, poi perché questo tipo di strumento, presente in tutte le versioni successive a VB6, non ha mai funzionato correttamente, costringendo i programmatori a riscrivere buona parte del codice.

Fortunatamente, il controllo Webbrowser era ancora disponibile in VB2008 e così, in poche ore, ho riscritto interamente il progetto, rinominandolo "Traveler", per distinguerlo meglio dal vecchio e buon "Skipper". Naturalmente la struttura è rimasta la stessa: una finestra di tipo MDI e più finestre figlie con al loro interno il controllo Webbrowser che occupa l'intero spazio messo a disposizione dalle Child. So, we can start with the project! Can we?

Iniziamo
Avviamo Visual Basic 2008 - io uso la versione Express, scaricabile gratuitamente dal sito Microsoft. Il download del software richiede la registrazione da parte di chi usufruisce del servizio. Tutto gratuito e legale. Anche con la versione express si può sviluppare software commerciale.

Scegliamo sulla sinistra della finestra di VB (Visual Basic 2008) "Create Project", diamo il nome "Traveler" al progetto e accettiamo con un click sul pulsante "OK". Rinominiamo "Travel" il form presente nel progetto e inseriamoci il controllo "Webbrowser". Nelle proprietà, indichiamo che il controllo dovrà occupare l'intero spazio messo a disposizione dalla finestra "Travel". Possiamo accedere alle proprietà di un oggetto presente nell'IDE (disegnato), nella parte destra della finestra di progetto, l'IDE appunto.

Inseriamo una nuova form nel progetto, diamogli il nome del progetto stesso e definiamola, sempre attraverso le proprietà, finestra MDI. A questo punto possiamo definirla come form di avvio. Queste istruzioni, possono essere facilmente seguite da chi abbia un poco di esperienza nell'uso di VB.

Per avviare una finestra figlia, basterebbe inserire la seguente istruzione in un evento della form MDI:

    Travel.Show()

Dove "Travel" è il nome della form che vogliamo avviare, e Show altro non è che il vecchio metodo presente fin dalle prime edizioni di VB, il quale avvia una istanza dell'oggetto form di nome, in questo caso, "Travel".

Ma dato che noi vogliamo creare più istanze della stessa finestra (form), il codice adatto a questo scopo sarà il seguente:

    Dim ChildForm As New Travel 'System.Windows.Forms.Form
    ChildForm.MdiParent = Me
    m_ChildFormNumber += 1
    ChildForm.Text = "Window " & m_ChildFormNumber
    ChildForm.Show()

Si crea un oggetto ChildForm (finestra figlia), si imposta il nome che apparirà nella barra del titolo a "Windows" (facoltativo, si può anche dare il nome che si ritiene più opportuno). Con ChildForm.Show() si visualizza la finestra. Con questo stesso codice, si possono creare più istanze della stessa finestra. Quindi se si disegna correttamente la finestra "Travel", tutte le istanze ottenute di questa finestra, funzioneranno correttamente.

Tutto il "poco" codice scritto per questo progetto è disponibile nel progetto stesso.

Ho inserito nel progetto una finestra "Splash" e una finestra "About", per abitudine, ma sono assolutamente inutili al fine del progetto.

Istruzioni per navigare
Ogni finestra Child (figlia) riceve ordini, se attiva, dalla finestra MDI (madre), questo significa che la MDI possiede i comandi necessari a identificare la finestra Child attiva e invia i comandi a questa e solo a questa. La finestra Child attiva, oltre ad eseguire il comando ricevuto, invia una risposta alla finestra madre. Complicato? Solo in apparenza, in quanto il codice è diretto e di poche righe, facile da comprendere per chiunque.

Dopo aver avviato una nuova form Child, il controllo Webbrowser nella Child mostra la pagina iniziale, che ho impostato nelle proprietà durante la programmazione visuale nell'IDE. La pagina iniziale così impostata, non è sostituibile, ma sarà facilissimo per chiunque, creare un piccolo file di configurazione che permetta di memorizzare alcuni parametri di configurazione, al fine di poter personalizzare un poco il progetto in fase di esecuzione.

I comandi per navigare sono i seguenti, ed appartengono tutti all'oggetto Webbrowser (fra parentesi quadre le istruzioni da sostituire []):

    Webbrowser.Navigate([indirizzo web valido])
    WebBrowser.GoBack()
    WebBrowser.GoForward()
    WebBrowser.Refresh()

Le quattro righe di codice sopra riportate, sono i comandi fondamentali per la navigazione. Navigate permette di mostrare la pagina web corrispondente all'indirizzo specificato all'interno delle parentesi. GoBack, GoForward e Refresh altro non fanno che dare la possibilità di muoversi fra le pagine precedentemente caricate o ritornare a una pagina da cui è tornati indietro e infine di ricaricare la pagina visualizzata.

Per identificare la finestra attiva, fra quelle eventualmente caricate all'interno della MDI, il codice è il seguente:

    Dim activeChild As Form = Me.ActiveMdiChild
    Dim Cont As WebBrowser

    If (Not activeChild Is Nothing) Then
      Try
        For Each Cont In activeChild.Controls
          If Cont.Name = "WebBrowser1" Then
            Cont.Navigate(ToolStripComboBox1.Text.ToString())
            Parla.SpeakAsync(ToolStripComboBox1.Text.ToString())
          End If
        Next
      Catch
        MessageBox.Show("Non esistono pagine Web attive!" & vbCrLf & _
                        "Per visualizzare uan pagina, bisogna avere una finestra attiva.")
      End Try
    End If

Questo codice scritto all'interno della MDI, permette di determinare quale sia il form attivo e inviargli uno o più comandi. E' inserito negli eventi di menù o della Toolbar della MDI

Sempre in un evento di menù o delle Toolbar, il codice seguente chiude tutte le form figlie con un solo comando, utile per evitare al termine della navigazione di dover terminare singolarmente tutte le finestre aperte. Comunque, terminando la MDI, vengono chiuse tutte le finestre figlie.

    For Each ChildForm As Form In Me.MdiChildren
      ChildForm.Close()
    Next

A proposito, il testo colorato che forma il codice appena riportato, è come appare in Visual Basic 2008 Express Edition, I colori servono a far capire, al solo sguardo esperto del programmatore, di che genere di codice si tratti (risatina sarcastica).

Infine
La cosa magnifica, che bisogna notare assolutamente, è che nella finestra Child non è stato scritto codice, tutto funziona con le chiamate dalla MDI. Unico codice che ho ritenuto di dover scrivere è il seguente per l'evento Navigated dell'oggetto Webbrowser, riportato con la completa intestazione dell'evento:

    Private Sub WebBrowser1_Navigated(ByVal sender As Object, _
                                      ByVal e As System.Windows.Forms.WebBrowserNavigatedEventArgs) _
                                      Handles WebBrowser1.Navigated
        Me.Text = Me.WebBrowser1.Url.ToString
    End Sub

Il browser è fatto!

Non tutto è stato detto, scritto, in queste succinte pagine, ma dando una occhiata al progetto, lo troverete veramente banale e vi sarà inoltre molto facile apportarvi miglioramenti ed aggiunte.

Un tocco di Classe; inutile?
Seguendo le indicazioni di un altro programmatore, che gentilmente le aveva rese disponibili in Internet, ho aggiunto la possibilità di avere una speaker personale in aiuto ai navigatori del web. Cosa voglio dire? Semplice, aggiungendo al progetto, la seguente direttiva:

Imports System.Speech.Synthesis

si ha la possibilità di accedere alla libreria "System.Speech.dll", la quale permette di elaborare una accettabile sintesi vocale in Windows. Naturalmente, servirà procurarsi una voce che abbia una pronuncia italiana. Su Microsoft era disponibile la libreria di ScanSoft, con una nuova voce, "Silvia", che ha un timbro di voce carino e pronuncia correttamente la lingua italiana. Procurarsi la voce Silvia non è più facile: dovete cercare in rete "text-to-speech scansoft silvia" e troverete diversi siti da cui fare il download.

Installare la nuova voce nel proprio PC, e creare un oggetto di tipo SpeechSyntetizer:

  Dim Parla As New SpeechSynthesizer

a questo punto bisognerà dire al sistema di usare la voce Silvia al posto della voce Anna che è la voce di default per Windows. Anna possiede una pronuncia anglofona.

Tutte le volte che si vorrà far leggere a "Silvia" un testo, basterà passare il testo sotto forma di variabile stringa o testo fra doppie virgolette al metodo SpeakAsync:

    Parla.SpeakAsync("benvenuti nel nuovo modo di consultare il web")

SpeakAsync permette di leggere il testo passatogli come parametro senza interrompere i processi in corso, riproducendo l'audio in modo asincrono, al contrario di quanto accadrebbe con il metodo Speak.

A cosa può servire tutto questo?

Semplicemente a nulla, se non si specializza il progetto per scopi come:

Nota importante:
nel progetto, non tutti i pulsanti ed i menù sono funzionanti, dato che sono partito da un progetto preconfezionato, disponibile in VB2008, modificando solo quello che mi serviva.

Per critiche o suggerimenti su questo Ignobile progetto potete scrivere a
Emilio Scaccaglia (MSDE) o visitare il mio sito, sul quale potrete trovare mie note personali.