Articolo

Come utilizzare le icone a 32bit di Windows XP

PREMESSA

In questo articolo tratteremo il problema di incompatibilità tra il Visual Basic 6.0 (ma anche VB.NET non è immune al 100% da questo problema) e le icone a 32 bit con canale Alpha (quelle di Windows XP, per capirci). Potrebbe anche essere che il problema qui descritto non vi sia mai capito (come è accaduto a me fino a poco tempo fa) ma per la nota legge di Murphy prima o poi... Ed infatti a me è capitato!

Microsoft Windows 3.1 ci aveva abituato con le icone 32x32 a 16 colori, poi con l'avvento di Windows 95 le icone iniziarono ad contenere due formati: 16x16 e 32x32. Oggi le cose sono molto cambiate, le icone possono contenere decine di immagini in diversi formati, tra cui le icone a 32bit.
Poter quindi utilizzare anche le nuove icone di Windows XP a 32bit è molto importante. Dobbiamo infatti riconoscere che le nuove icone sono veramente belle ed occorre quindi esser pronti per offrire un prodotto sempre più accattivamente anche dal punto di vista grafico.

IL PROBLEMA

Questo problema si riscontra ogni volta che si tenta di caricare un'icona a 32bit da Visual Basic in qualsiasi controllo grafico (Form, PictureBox, Image, ecc.). Tentando infatti questa operazione Visual Basic risponde con un bel messaggio (si fa per dire):

Immagine non valida (Errore 481)

La descrizione dell'errore dice:

È stato assegnato un formato grafico non valido alla proprietà Picture. Causa e soluzione dell'errore:

Si è cercato di assegnare un formato grafico diverso da bitmap, icona o metafile di Windows alla proprietà Picture di un form o controllo.
Verificare che il file che si sta cercando di caricare nella proprietà Picture sia un file grafico valido supportato da Visual Basic.

Eppure siamo sicuri: è un'icona!

Come dicevo nella premessa, anche io fino ad ora non avevo mai riscontrato questo problema, o meglio l'avevo incontrato ma pensavo che fosse dipeso da una immagine corrotta. Tra l'altro per le mie toolbar ho sempre preferito utilizzare icone con un massimo di 256 colori in quanto potevo utilizzare le stesse immagini anche per i menu!

Qualche giorno fa, Marc Emile della Axialis Software che produce programmi grafici (Icon Workshop, AX Cursor,...) mi dice che molti suoi clienti, sviluppatori VB) si lamentano perchè riscontrano questo problema e mi chiede se io so come risolverlo.
Naturalmente casco dalle nuvole... Decido di fare qualche prova ed in effetti scopro che è proprio così! Possibile che non me ne sia mai accorto? A quanto pare... non sono l'unico! Quindi comincio a studiare il problema e mi accorgo subito di una cosa strana: non sempre ricevevo il fantomatico errore. Con alcune icone sì, con altre no. E mi domando: "Perchè?"

Ovviamente sapendo che un'icona può contenere diversi tipi di immagine con colori e dimensioni diverse, la prima cosa che mi viene in mente è quella di indagare in questo senso analizzando diversi files ICO (con Icon Workshop di Axialis) per scoprire quali differenze potevano esserci. Alla fine ho capito che si possono verificare i seguenti due casi:

  1. l'icona contiene solo immagini a 32bit (canale Alpha - XP), si riceve l'errore.


    Figura 1
  2. l'icona contiene immagini in vari formati (oltre a quelle a 32bit) non si riceve l'errore.


    Figura 2

Nel secondo caso, sembrerebbe quindi andare tutto bene. Purtroppo non è così!
Infatti Visual Basic, quando carica una di queste icone, sceglie arbitrariamente quale immagine visualizzare tra quelle contenute.
Morale, vi può accadere di veder visualizzata un'immagine diversa da quella che vi aspettavate! Il risultato dipende da quali formati sono contenuti nell'icona.

LA PROVA

Per dimostrarvi quanto appena detto vi mostro un'icona che ho volutamente modificato proprio per far comprendere inequivocabilmente il misfatto. Osserviamo l'icona modificata:

come potete vedere è composta da 9 immagini di cui le prime 3 raffigurano il punto interrogativo, mentre le altre 6 il punto esclamativo:


Figura 3


Figura 4

Tengo a precisare che l'icona in questione (wrong1.ico), se visualizzata in Explorer, mostra correttamente il punto interrogativo.

Qui a sinistra vedete la lista delle icone che ho allegato al progetto di esempio, tutte mostrano la stessa immagine.
Ma quando si caricano in Visual Basic l'immagine non è sempre quella desiderata.

Un esempio pratico
Supponiamo che vogliate caricare quest'icona in un PictureBox, dalla finestra di dialogo Apri vedreste il punto interrogativo (come in figura 4). Selezioniamo il file WRONG1.ICO, confermiamo con OK, ma una volta chiusa la finestra ci troviamo una bella sorpresa... VB non ci mostra il punto interrogativo, ma quello esclamativo e, per giunta, ha caricato l'immagine peggiore: l'ultima. Che tra l'altro è monocromatica e quindi nemmeno trasparente!


Figura 5 - l'icona caricata

Non è sconcertante?

A questo punto sorge spontanea una semplice domanda: Come facciamo a caricare sempre l'immagine che volgiamo noi (invece di quella che scieglie VB)?
Idea! Perchè non mettiamo l'icona che ci interessa in file di risorse (RES) e la carichiamo da lì? Peccato purtroppo che anche in questo caso VB si rifiuta di caricare icone a 32bit! (Più avanti spiegherò anche come risolvere a questa limitazione)

SOLUZIONE DEL PROBLEMA

La sola soluzione possibile è quella di caricare le icone come risorsa, più semplice a dirsi che a farsi, però. Perchè qui non si parla di estrarre le icone nel metodo 'standard' (vi sono migliaia di progetti sulla rete che estraggono icone da EXE e DLL) ma in questo caso, scusate se lo ribadisco, si devono estrarre SOLO determinate immagini appartenenti ad un'icona, non l'icona completa!

In questo articolo non descriverò il codice sorgente perchè ci vorrebbe molto di più di un articolo! Lascio questo esercizio a chi desidera approfondire le proprie conoscenze sull'argomento. Naturalmente siete liberi di utilizzare il codice e le funzioni che trovate nel progetto a vostro piacere.

Qui mi limiterò solo a descrivere il funzionamento di questo progetto.
Dovrete scusarmi, ma avendolo preparato in inglese non ho pensato a tradurlo, ma è talmente semplice che non credo vi siano difficoltà nel comprenderlo.


Figura 6 - Il progetto di esempio

Il progetto dimostra come caricare 'selettivamente' le immagini contenute nelle icone contenute in file EXE o DLL, cioè solo le icone che corrispondano ad una determinata dimensione e profondità di colore (stabilita tramite le opzioni impostate nei gruppi Size e Color depth).
Una volta acquisite le immagini richieste, le carica in un controllo ImageList che a sua volta viene poi collegato ad una ToolBar ed ad un ImageCombo (in basso a sinistra) per poter visualizzare le immagini.
La ToolBar visualizza solo alcune delle immagini caricate, mentre nell'ImageCombo potrete vederle tutte, e per ognuna ne viene indicato il numero, lo spazio occupato in bytes e le dimensioni.

Nell'esempio in figura 6 possiamo notare che la toolbar ha caricato solo le icone a 32bit formato 48x48 contenute nel file Explorer.exe, in base a quanto indicato appunto dai pulsanti di opzione nei due gruppi Size e Color depth.
Nella barra di stato vediamo indicato che il numero delle immagini corrispondenti a quanto richiesto è 9 (Explorer.exe ne contiene invece 113 in totale).

Selezionando la casella All Size and Formats, quando premete il pulsante Load Icons verranno caricate tutte le risorse icone contenute nel file selezionato dalla lista. Ecco allora che la listbox Other formats (if any) tornerà utile perchè nel file, logicamente, vi possono essere anche altre immagini di formato diverso (parliamo sempre di icone).
Osserviamo la figura 7:


Figura 7 - Tutte le icone di Explorer.exe

In questo caso abbiamo caricato tutte le icone di Explorer.exe (113 immagini) e vedete che a destra la ListBox elenca 3 icone che non rientrano in nessuno dei formati diciamo così 'predefiniti'. Infatti sono icone monocromatiche, di cui la prima la potete vedere nell'ImageCombo a sinistra.

Noterete che alcune icone visualizzate sulla ToolBar risultano distorte; questo perchè, come ben sapete, la ToolBar e l'ImageList possono visualizzare immagini in un solo formato quindi tutte le altre vengono 'adattate'.


COME CREARE LIBRERIE DI ICONE A 32BIT

Ora che abbiamo visto come estrarre le immagini dalle icone dei files EXE/DLL e visualizzare nei nostri controlli, non resta che trovare il modo di creare le nostre librerie.

Anche se la cosa è fattibile, nel progetto non ho intenzionalmente affrontato la questione di caricare le icone da files ICO per due motivi:

  1. perchè mi sembra abbastanza banale
  2. perchè non è assolutamente pratica

Infatti sarebbe assai più comodo riunire tutte le icone che volgiamo utilizzare in una libreria, e caricarle a run-time. La creazione di una libreria (DLL) di icone tramite il Visual Basic è normalmente un'operazione alquanto banale.
Purtroppo, come ho già detto, questo non vale per le icone a 32bit (con canale Alpha) che il Resource Editor rifiuta categoricamente, al pari degli altri controlli grafici.

Come fare, allora?

Come ben sanno i programmatori di lunga data, esiste un programma che si chiama Resource Compiler (RC.EXE) che viene tutt'ora distribuito con il Visual Basic. Per quelli che hanno il Visual Studio lo possono trovare nella cartella:

C:\Programmi\Microsoft Visual Studio\VB98\Wizards\

oppure

C:\Programmi\Microsoft Visual Studio\Common\MSDev98\Bin

Nota storica: il Resource Compiler, ai tempi del VB3 era l'unico programma con cui i programmatori VB potevano creare i files di risorse (RES) anche se poi da lì a creare una libreria DLL la cosa non era così semplice per loro.

Per creare la nostra libreria procediamo in questo modo:

  1. Create un file di script (con il Blocco Note) in cui elencate le risorse icona, in questo modo:

    ///////////////////////////////////////////////
    //
    // Icons
    //
    ///////////////////////////////////////////////

    101 ICON MOVEABLE PURE "cd rom drive.ico"
    102 ICON MOVEABLE PURE "control panel.ico"
    103 ICON MOVEABLE PURE "default document.ico"
    104 ICON MOVEABLE PURE "entire system.ico"
    105 ICON MOVEABLE PURE "favorites.ico"
    106 ICON MOVEABLE PURE "floppy drive.ico"

    ecc.
  2. Salvate il file con estensione .RC (esempio MYICONS.RC)
    Naturalmente il file .RC va creato nella stessa cartella in cui risiedono le icone!
  3. Quindi lo compilate con il Resource Compiler, tramite il comando al Prompt del DOS:

    RC MYICONS.RC
    (più avanti vi sarà un suggerimento su questa operazione)

    e otterrete così il file di risorse MYICONS.RES.
  4. Ora avviate Visual Basic e create un nuovo progetto ActiveX/DLL
    Vi troverete un progetto con una sola classe (Class1)
  5. Aggiungete al progetto il vostro file di risorse MYICONS.RES
    Consiglio di non modificarlo o aprirlo con il Resource Editor!
  6. Nominate il progetto (es. MyIcons)
  7. Infine compilate il progetto (File>Crea MyIcons.dll...)

Ecco fatto, avete creato la vostra libreria di icone!

Nel progetto di esempio ho allegato anche 4 librerie di icone create proprio in questo modo, che contengono esclusivamente icone a 32bit con canale Alpha:

  1. XP_icons_16.dll (icone 16x16 a 32bit)
  2. XP_icons_24.dll (icone 24x24 a 32bit)
  3. XP_icons_48.dll (icone 48x48 a 32bit)
  4. XP_icons_all.dll (icone 16x16, 32x32, 48x48 a 32bit)

Come vedete le prime tre contengono solo immagini della stessa dimensione, mentre l'ultima contiene formati misti. Voi potete creare librerie con le immagini in base alle vostre esigenze: se ad esempio volete fornire all'utente di poter cambiare la dimensione dei pulsanti della toolbar (come avviene in Esplora risorse) da 16 a 24, potete includere nella libreria entrambi i formati e poi caricare a run-time quello richiesto dall'utente.
Tra l'altro, il fatto di includere solo le immagini che utilizzate vi permette di risparmiare spazio inutile (e memoria): perchè caricare 12 formati quando ne uso solamente 2?

Nel progetto di esempio potete fare questa prova: selezionate il file XP_icons_16.dll dalla lista, e poi impostate Size a 16 e Color Depth a 16. Premete Load Icons e vedrete che non viene caricata alcuna icona. Perchè? Perchè le librerie contengono SOLO immagini a 32bit. Se impostate Size su 16 e Color Depth su Win XP le immagini verranno caricate regolarmente.

 

Suggerimento sul Resource Compiler

Se qualcuno si trova in difficoltà nella compilazione con RC.EXE (perchè non sa come aprire una sessione DOS, o perchè digitare da DOS tutti i percorsi completi potrebbe essere noioso) io uso questo sistema:

Copio i due files RC.EXE e RCDLL.DLL nella cartella che contiene le icone ed il file MYICONS.RC, poi direttamente da Esplora risorse trascino il file MYICONS.RC sul file RC.EXE.
In un attimo ottengo il file RES.

Per chiudere, una nota interessante

Nel progetto ho utilizzato i controlli Windows Common Controls 6.0 (SP6) ma potete utilizzare tranquillamente anche quelli della versione 5.0 (SP2) che ad esempio visualizza la toolbar nello stile di XP. Inoltre il codice di questo progetto utilizzato con la versione 5.0, vi permette di visualizzare correttamente nella toolbar anche le icone a 256 colori, che invece risultano veramente brutte.

 

CONCLUSIONE

Sicuramente gli amanti della grafica apprezzeranno molto il codice sorgente utilizzato in questo progetto.

Spero anche che questo articolo possa contribuire ad aiutarvi nella creazione di interfaccie grafiche sempre più accattivanti. Anche perchè (non bisogna mai dimenticarlo) anche l'occhio vuole la sua parte!

Naturalmente il progetto è stato realizzato a scopo puramente didattico, lungi dall'essere perfetto.
Se qualcuno apporterà dei miglioramenti sarei felice di esserne informato.

Giorgio Brausi