martedì 7 febbraio 2012

[VB.NET] Utilizzare Resources

Descrizione :
Un mio esempio pratico per utilizzare files di Risorse.

+ Articolo :

Argomento sicuramente già molto documentato sul Web.
I Files di Risorsa permettono di incorporare suoni, immagini, testi e quant'altro nell'eseguibile stesso.
Di documentazione in giro ce n'è tanta. Quello che forse manca, a mio avviso, sono esempi chiari e definitivi.
Molti "tutorial" poi, all'atto pratico, non funzionano, oppure utilizzano codice eccessivo, o ancora eseguono percorsi che secondo me si possono evitare tranquillamente.
Perciò inserisco questo semplice Articolo, con la dimostrazione pratica di alcune mie convinzioni sull'argomento :

1. Nessun bisogno di "ricavare" il file dalla Risorsa in cui è stato incluso, andando a ricostruire il nome originario, concatenando il percorso ( Assembly ), il nome, e addirittura l'estensione originaria.

2. Tutto può essere gestito seguendo la semplice logica dei pochi Oggetti e Metodi davvero necessari :
ResourceManager --> ResourceSet --> .GetObject().

3. Un UnmanagedMemoryStream, che è quanto restituito in uscita dalla Risorsa, può essere semplicemente assegnato all'Oggetto che lo deve utilizzare :
--> in VB, direttamente.
--> in C#, con un semplice Cast sul tipo di destinazione richiesto.

4. In particolare, per quanto riguarda l'esecuzione di Stream audio da file, tipicamente .WAV inclusi nelle Risorse, nessun bisogno di dichiarazioni/chiamate API, o peggio  ancora, controlli ActiveX "nascosti" o altro.
Basta un semplice System.Media.SoundPlayer per questo genere di cose, tanto in VB quanto in C#.

Per replicare l'esempio seguente basta una semplice Form "FormMain" con i seguenti controlli :
--> ComboBox : cmb_suoni
--> PictureBox : pbx_img
--> RichTextBox : rtb_testo

A questo punto, se ci si vuole semplificare ulteriormente le cose, si crea un File .resx per ogni gruppo omogeneo di Risorse.
Nel caso dell'esempio in questione :
--> SUONI.resx : SOUND_1.WAV, SOUND_2.WAV, SOUND_3.WAV.
--> IMMAGINI.resx : SOUND_1.jpg, SOUND_2.jpg, SOUND_3.jpg.
--> TESTI.resx : SOUND_1.txt, SOUND_2.txt, SOUND_3.txt.

La figura seguente per definire meglio il concetto :


--> Codice FormMain :
Public Class FormMain

    Private nomeProgetto As String = Reflection.Assembly.GetExecutingAssembly.GetName.Name

    Private Function GetResxFiles(ByVal nomeFileResx As String) As Resources.ResourceSet

        'Nome Risorsa senza estensione .resx
        Dim RM As New Resources.ResourceManager(nomeProgetto & "." & nomeFileResx, Reflection.Assembly.GetExecutingAssembly())
        Dim RS As Resources.ResourceSet = RM.GetResourceSet(Globalization.CultureInfo.InvariantCulture, True, False)
        Return RS

    End Function

    Private Function GetResxFile(ByVal nomeFileResx As String, ByVal nomeRisorsa As String) As Object

        Return GetResxFiles(nomeFileResx).GetObject(nomeRisorsa, True)

    End Function

    Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim listaSuoni As New List(Of String)
        For Each DE As DictionaryEntry In GetResxFiles("SUONI")
            listaSuoni.Add(DE.Key)
        Next
        listaSuoni.Sort()
        With cmb_suoni
            .DropDownStyle = ComboBoxStyle.DropDownList
            .Items.AddRange(listaSuoni.ToArray)
            .SelectedIndex = 0
        End With

    End Sub

    Private Sub cmb_suoni_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmb_suoni.SelectedIndexChanged

        'Play Risorsa Audio
        Using SP As New System.Media.SoundPlayer
            SP.Stream = GetResxFile("SUONI", cmb_suoni.SelectedItem)
            SP.Play()
        End Using

        'Assegna Risorsa Immagine
        pbx_img.Image = GetResxFile("IMMAGINI", cmb_suoni.SelectedItem)

        'Assegna Risorsa Testo
        rtb_testo.Text = GetResxFile("TESTI", cmb_suoni.SelectedItem)

    End Sub

End Class

La soluzione è pulita e funzionante : il ResourceManager genera un ResourceSet, che espone parecchi Metodi utili, tra cui .GetObject(), perciò direi che altro non serve.

+ Fine Articolo.


Un Click su "Mi Piace" è il modo migliore per ringraziare l'autore di questo articolo.



6 commenti:

Giovanni Lacchei ha detto...

Public Module Grazie
Public Sub Main()
For i As Integer = 1 To 10000
Console.WriteLine("Grazie!!")
Next i
End Sub
End Module

Davide Maggioni ha detto...

E' possibile inserire nelle resources anche una dll (e poi utilizzarla)? Nel mio caso la SharpZipLib

MarcoGG ha detto...

La domanda suona un po' strana. Una libreria è a tutti gli effetti "Codice Eseguibile", mentre un file di risorsa no. Scopo principale delle risorse è quello di accorpare nel compilato ( tipicamente l'exe in Release... ) dei file che non contengono istruzioni, ma che sono utili all'esecuzione. Le librerie non si uniscono come risorse, ma si referenziano nel progetto. Oltretutto, posto che fosse possibile, e al mio attuale stato di conoscenza, ci metterei un bel NO, avrebbe poco senso sul lato pratico. Una DLL ( che come dice il nome stesso : Dynamic Link Library ) viene creata proprio per scorporare un exe che altrimenti, in applicazioni complesse, arriverebbe a pesare troppo...

Davide Maggioni ha detto...

Allora come posso fare per importare ed utilizzare una dll?

MarcoGG ha detto...

Questa è un'operazione standard di Visual Studio :
Proprietà di progetto / Riferimenti / Aggiungi riferimento / Sfoglia ...

Anonimo ha detto...

Grazie :)

Posta un commento

 
Design by Free WordPress Themes Modificato da MarcoGG