Utilizziamo il controllo in oggetto all'interno del progetto Happy Sign. Serve per creare quelle simpatiche barre simili a questa qui sotto..
In pratica, una serie di container (chiamati Expando) che possono contenere un certo numero di items (che possono essere qualsiasi controllo che deriva da Control, appunto). E' liberamente disponibile su Code Projects, e non fanno capo ad un qualche team, ma ad un certo Mathew Hall. Ho preferito questo controllo a diversi altri che ho cercato negli ultimi giorni, primi fra tutti quello pubblicato da vbAccelerator, che usavamo prima, e quelli invece che vengono usati da Janky e da Marco per il loro NHibernateDomainMapper. Ho diversi motivi per preferire questo: molti effetti grafici, supporto del drag'n'drop, e soprattutto - quasi un must - l' auto-arrange degli items quando questi vengono aggiunti a run-time come succede in Happy Sign. Quest'ultimo punto è fondamentale, perchè se all'interno di un Expando aggiungo n Items via codice, questi vengono direttamente disegnati seguendo il layout corretto, e senza dover impostare manualmente posizione o padding. Non solo: se aggiungo o rimuovo un item, l'Expando si ridimensiona correttamente. Anche con gli altri è possibile, ovviamente, ma è molto più laborioso.
Ma. C'è sempre un ma. Il Themed Windows XP Style Explorer Bar non funziona sotto Windows Vista! :-((( Quando questo controllo viene usato sotto Vista - come me in questo momento - appare completamente sballato!
Fino a questa sera, però, perchè dopo aver macinato P/Invoke, analizzato lo stack delle chiamate e aver letto riga per riga il source code che mi interessava, ho raggiunto una soluzione che - sebbene non sia propriamente pulita - è affidabile ed efficiente. La morale è che per disegnarsi, il controllo va a leggere il tema corrente di Windows. Quando Windows è Windows XP, il file è C:\Windows\Resources\Themes\Luna\Shell\NormalColor\shellstyle.dll, mentre se è Vista diventa C:\Windows\Resources\Themes\Aero\Shell\NormalColor\shellstyle.dll. Ovviamente, i files hanno dimensioni e struttura completamente diverse. La routine GetShellStylePath() nella classe ThemeManager si occupa di ritornare il path del file, che poi verrà letto da un parser che estrae le risorse necessarie. Invece di ritornare il filename del tema corrente, ritorno un mio filename, che punta ad un file shellstyle.dll tutto mio, prelevato direttamente da Windows XP. Quindi:
private static string GetShellStylePath()
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
string stylePath = Path.GetDirectoryName(currentAssembly.Location);
stylePath += @"\shellstyle.dll"
return(stylePath);
}
Non fate molto affidamento sul codice, ci sto ancora lavorando. Così facendo, il tema corrente dell'OS viene completamente ignorato, e viene invece utilizzato il file shellstyle.dll che si trova nello stesso folder in cui si trova l'assembly che sta girando. Sebbene venga fisicamente utilizzato un file proprio di XP, vi assicuro che la differenza non si nota affatto!
Sono proprio contento, onestamente, perchè googlare all'infinito alla ricerca di un controllo non è il massimo della vita! ;-)
Un'ultima cosa. Chi volesse usare il controllo scaricandolo da Code Projects, troverà un errore riguardante P/Invoke:
A call to PInvoke function 'XPExplorerBar!XPExplorerBar.NativeMethods::LoadBitmap' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
Come dico il testo dell'errore, abbiamo importato una funzione nativa in managed code, senza rispettare però il tipo dei parametri o le chiamate. Nella fattispecie, nella classe NativeMethods occorre modificare l'import della LoadBitmap in questo modo:
[DllImport("User32.dll")]
public static extern IntPtr LoadBitmap(IntPtr hInstance, int lpBitmapName);
Il secondo parametro, lpBitmapName non è di tipo long, ma int. Modificatelo come vi dico, e non avrete più problemi.