I miei freeware http://blogs.ugidotnet.org/idamiani/category/I miei freeware.aspx Sviluppo dei miei software freeware, avanzamento dei lavori, proposte, discussioni e analisi it-IT Igor Damiani Subtext Version 2.6.0.0 Nuove features ed un nuovo installer per il mio emoticons plug-in http://blogs.ugidotnet.org/idamiani/archive/2007/02/19/71116.aspx <p>Ieri mattina, sfruttando un po' di tempo libero, ho preparato un nuovo installer per il mio famigerato plug-in per Windows Live Writer, con le funzionalità di cui parlavamo l'altra volta. In particolare sottolineo:</p> <ol> <li>le emoticons vengono salvate in <strong>C:\Documents and Settings\All Users\Application Data\VivendoByte Emoticons</strong></li> <li>è possibile organizzare le emoticons in più subfolders rispetto alla directory del punto (1)</li> <li>quando si clicca su una emoticon, oltre alla preview in basso a sinistra, appare anche l'url che verrà utilizzata per l'inserimento dell'emoticon stessa</li> <li>ho diminuito <em>di un po'</em> la dimensione dei Button per ciascuna emoticon</li></ol> <p>L'installer è in formato MSI, ed è liberamente scaricabile dallo stesso URL dell'altra volta, <a href="http://www.igordamiani.it/download.php?id=16" target="_blank">cioè da qui</a>. L'installer verifica che abbiate installato Windows Live Writer, altrimenti si interrompe: segnalatemi eventuali problemi. L'installer di default installa tutto dentro la directory <strong>C:\Program Files\VivendoByte\VivendoByte Emoticons plug-in</strong>, come riportato qui sotto:</p> <p><img src="http://www.igordamiani.it/blog/plugin_installed.JPG"> </p> <p>E'&nbsp;necessario (per adesso)&nbsp;eseguire a mano <strong>Install.bat</strong> per copiare la dll dentro il path di Windows Live Writer e per copiare le emoticons nel posto giusto. Il file batch è abbastanza semplice:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:dc810503-fe40-4997-bea3-82c1c2fbca02" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">xcopy</span><span style="color: #000000; "> VivendoByteEmoticons</span><span style="color: #000000; ">.</span><span style="color: #000000; ">dll </span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">%ProgramFiles%\Windows Live Writer\Plugins</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> </span><span style="color: #000000; ">/</span><span style="color: #000000; ">Y </span><span style="color: #0000FF; ">mkdir</span><span style="color: #000000; "> </span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">%ALLUSERSPROFILE%\Application Data\VivendoByte Emoticons</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">xcopy</span><span style="color: #000000; "> </span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">VivendoByte Emoticons\*.*</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">%ALLUSERSPROFILE%\Application Data\VivendoByte Emoticons</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> </span><span style="color: #000000; ">/</span><span style="color: #000000; ">Y</span></div></pre></div></p> <p>Utilizzo qualche variabile d'ambiente per essere sicuro di copiare le cose giuste nel posto giusto. Declino ogni responsabilità di scrittura di files in post indesiderati. Sulle altre cose sto lavorando con calma. Se oggi ho tempo faccio richiesta su CodePlex, così sarà disponibile a tutti anche il codice sorgente, che può fare comodo.</p> <p><a href="http://www.igordamiani.it/download.php?id=16" target="_blank">Scarica il plug-in da qui</a></p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/71116.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/19/71116.aspx Mon, 19 Feb 2007 13:48:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/19/71116.aspx#feedback http://blogs.ugidotnet.org/idamiani/comments/commentRss/71116.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/71116.aspx Un FolderButton per il VivendoByteEmoticons plug-in http://blogs.ugidotnet.org/idamiani/archive/2007/02/15/70867.aspx <p>L'altra volta avevo accennato all'idea di poter organizzare le emoticons in sotto-folder, contenuti in: <em><font color="#008040">C:\Documents and Settings\All Users\Application Data\VivendoByte Emoticons</font></em>. Notare che la directory non è più <em>per-user</em>. Questo implica il fatto che una volta che il plug-in viene installato, tutti gli utenti condividano lo stesso set di emoticons. Niente di male, direi.</p> <p>L'altra volta avevo accennato al fatto che i Button che contengono le emoticons sono contenuti all'interno di un WrapPanel. Tale WrapPanel è definito nello XAML della Window ChooseEmoticon.</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:b8a31179-98e5-4cf6-bf41-4a786be86c85" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">WrapPanel </span><span style="color: #FF0000; ">Grid.Column</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #FF0000; "> Grid.Row</span><span style="color: #0000FF; ">=&quot;1&quot;</span><span style="color: #FF0000; "> Name</span><span style="color: #0000FF; ">=&quot;MainPanel&quot;</span><span style="color: #FF0000; "> ItemHeight</span><span style="color: #0000FF; ">=&quot;{StaticResource Size}&quot;</span><span style="color: #FF0000; "> ItemWidth</span><span style="color: #0000FF; ">=&quot;{StaticResource Size}&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">WrapPanel</span><span style="color: #0000FF; ">&gt;</span></div></pre></div></p> <p>La classe ChooseEmoticon dispone di un metodo privato <strong>populateIcons()</strong>, che viene chiamato nel costruttore e successivamente&nbsp;ogni volta che viene cambiata directory. Tale metodo fa quanto segue:</p> <ol> <li>svuota i Children del WrapPanel</li> <li>eventualmente aggiunge un pulsante per tornare su di una directory</li> <li>aggiunge tanti FolderButton quanti sono i sotto-folder presenti nella directory corrente</li> <li>aggiunge tanti Button quanti sono i files .GIF presenti nella directory corrente</li> <li>aggiorna la proprietà Text del TextBlock per indicare all'utente quante emoticons ci sono</li></ol> <p>Il punto (2) richiede un breve chiarimento. Non voglio che l'utente navighi al di fuori di <font color="#008040"><em>C:\Documents and Settings\All Users\Application Data\VivendoByte Emoticons</em></font><font color="#000000">, pertanto il FolderButton che torna su appare solo se ci troviamo in una sua sotto-directory, e non negli altri casi.</font></p> <p>Anche il punto (3) richiede un chiarimento. La classe FolderButton infatti non esiste nel FW3.0, ma l'ho creata io attraverso un piccolo blocco di XAML. Lo XAML&nbsp;ovviamente non serve solo a creare Window o Page, ma a creare qualsiasi classe. La classe FolderButton eredita da un normale Button, ma ne specializza l'aspetto: utilizza una risorsa <strong>folder.bmp</strong>, in modo tale da creare un pulsante che come contenuto ha un'immagine che fa capire che si tratta di una directory. Ecco lo XAML che ho utilizzato per definire la classe FolderButton:</p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:20096eed-e535-43be-8232-7b8f37fe49b7" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Button </span><span style="color: #FF0000; ">x:Class</span><span style="color: #0000FF; ">=&quot;VivendoByte.Emoticons.FolderButton&quot;</span><span style="color: #FF0000; "> xmlns</span><span style="color: #0000FF; ">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;</span><span style="color: #FF0000; "> xmlns:x</span><span style="color: #0000FF; ">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Grid</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Grid</span><span style="color: #FF0000; ">.ColumnDefinitions</span><span style="color: #0000FF; ">&gt;&lt;</span><span style="color: #800000; ">ColumnDefinition</span><span style="color: #0000FF; ">&gt;&lt;/</span><span style="color: #800000; ">ColumnDefinition</span><span style="color: #0000FF; ">&gt;&lt;/</span><span style="color: #800000; ">Grid.ColumnDefinitions</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Grid</span><span style="color: #FF0000; ">.RowDefinitions</span><span style="color: #0000FF; ">&gt;&lt;</span><span style="color: #800000; ">RowDefinition</span><span style="color: #0000FF; ">&gt;&lt;/</span><span style="color: #800000; ">RowDefinition</span><span style="color: #0000FF; ">&gt;&lt;/</span><span style="color: #800000; ">Grid.RowDefinitions</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Image </span><span style="color: #FF0000; ">Grid.Column</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #FF0000; "> Grid.Row</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">Image</span><span style="color: #FF0000; ">.Source</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">BitmapImage </span><span style="color: #FF0000; ">UriSource</span><span style="color: #0000FF; ">=&quot;Images/folder.bmp&quot;</span><span style="color: #FF0000; "> </span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">Image.Source</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">Image</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">TextBlock </span><span style="color: #FF0000; ">Name</span><span style="color: #0000FF; ">=&quot;folderName&quot;</span><span style="color: #FF0000; "> VerticalAlignment</span><span style="color: #0000FF; ">=&quot;Center&quot;</span><span style="color: #FF0000; "> HorizontalAlignment</span><span style="color: #0000FF; ">=&quot;Center&quot;</span><span style="color: #FF0000; "> Grid.Column</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #FF0000; "> Grid.Row</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; ">..</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">TextBlock</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">Grid</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">Button</span><span style="color: #0000FF; ">&gt;</span></div></pre></div> <p>Di&nbsp;default la classe FolderButton crea un Button con dentro l'immagine di un folder ed il cui testo è "..". Un FolderButton contiene una Grid con una sola riga ed una sola colonna. L'unica cella contiene sia l'immagine che un oggetto TextBlock, nel cui testo finisce il nome della directory a cui si fa riferimento. Notare che l'immagine viene caricata dalla&nbsp;risorsa <strong>/Images/folder.bmp</strong>: ovviamente tale file è stato inserito nella soluzione come <strong>Resource</strong>.</p> <p>Nel metodo <strong>populateIcons</strong> di cui parlavo prima, posso scrivere una cosa tipo:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:57d29e13-6e0c-4e02-a1c4-edc93c526b9b" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">private</span><span style="color: #000000; "> FrameworkElement getFolderElement(</span><span style="color: #0000FF; ">string</span><span style="color: #000000; "> directoryName) { FolderButton btn </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> FolderButton(); btn.ToolTip </span><span style="color: #000000; ">=</span><span style="color: #000000; "> directoryName; btn.Tag </span><span style="color: #000000; ">=</span><span style="color: #000000; "> directoryName; btn.MouseDoubleClick </span><span style="color: #000000; ">+=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> MouseButtonEventHandler(FolderDoubleClicked); </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> (btn); }</span></div></pre></div></p> <p>Questo metodo ritorna un'istanza di FrameworkElement: nella fattispecie proprio un FolderButton. Ad ogni istanza associo un tooltip, imposto il tag ed assegno l'handler per l'evento MouseButtonDoubleClick: quando l'utente <em>doppio-clicca</em> su un FolderButton, faccio altre cosine e richiamo la <strong>populateIcons()</strong> per reimpostare il WrapPanel.</p> <p>Vorrei sinceramente mettere altro codice, però il fatto di non poter avere scrollbar nei blocchi di codice causa la comparsa di post lunghi un chilometro: preferisco non farlo.</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70867.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/15/70867.aspx Thu, 15 Feb 2007 17:46:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/15/70867.aspx#feedback http://blogs.ugidotnet.org/idamiani/comments/commentRss/70867.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70867.aspx Definire StaticResource via codice ed usarle nello XAML http://blogs.ugidotnet.org/idamiani/archive/2007/02/13/70628.aspx <p>Ieri <a href="http://blogs.ugidotnet.org/jc/" target="_blank">Alessio</a> mi ha dato un'idea: da buon utente del mio plug-in, mi ha chiesto di ridurre <em>di un po'</em> (50-60%, dice lui) la dimensione dei Button che contengono&nbsp;le emoticons. Mi è sembrata una buona idea, ma poi ho pensato che fosse una cosa piuttosto soggettiva: c'è chi vorrebbe vederle grandi come una casa, e chi invece vorrebbe vederle minuscole per farcene stare di più a parità di dimensioni.</p> <p>Cosa c'è di meglio quindi che lasciar decidere a voi? All'interno della soluzione faccio già uso&nbsp;di un file&nbsp;<em><font color="#0000ff">VivendoByteEmoticons.settings</font></em>, che contiene alcuni settaggi specifici per ciascun utente. Per adesso, l'unico settings si chiama&nbsp;<strong>ImageUrl</strong> ed è il tag &lt;img/&gt; che viene usato per inserire l'emoticon all'interno del post. Ho quindi aggiunto un altro setting, chiamato <strong>Size</strong>, di tipo double, con un valore predefinito di 50. Ok, fin qua, ci siamo: abbiamo un post dove l'utente può scrivere la larghezza (e l'altezza, trattandosi di un quadrato) dei Button che contengono gli emoticons.</p> <p>Come facciamo ad utilizzarlo? Andiamo con calma.<br>Il WrapPanel è ovviamente definito nello XAML:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:234430d8-03cb-445a-b314-06e8a5795009" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 491px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">WrapPanel </span><span style="color: #FF0000; ">Name</span><span style="color: #0000FF; ">=&quot;MainPanel&quot;</span><span style="color: #FF0000; "> ItemHeight</span><span style="color: #0000FF; ">=&quot;70&quot;</span><span style="color: #FF0000; "> ItemWidth</span><span style="color: #0000FF; ">=&quot;70&quot;</span><span style="color: #FF0000; "> Grid.Column</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #FF0000; "> Grid.Row</span><span style="color: #0000FF; ">=&quot;1&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">WrapPanel</span><span style="color: #0000FF; ">&gt;</span></div></pre></div></p> <p>Il WrapPanel espone tra le altre cose due proprietà interessanti: <strong>ItemWidth</strong> e <strong>ItemHeight</strong>. E' abbastanza chiaro il loro scopo: ogni volta che viene un oggetto alla sua collection <strong>Children</strong> (un Button) tale oggetto assume le dimensioni indicate da queste due proprietà. Nella prima release, tale dimensione&nbsp;è - come si vede sopra -&nbsp;fissa, cablata nello XAML: 70 punti. Adesso dobbiamo fare in modo di utilizzare il setting <strong>Size</strong>&nbsp;di cui parlavamo prima. Dovremmo poter scrivere un qualcosa del tipo:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:193e89f1-ed3e-44ab-908b-4caf03936db7" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">WrapPanel </span><span style="color: #FF0000; ">Name</span><span style="color: #0000FF; ">=&quot;MainPanel&quot;</span><span style="color: #FF0000; "> ItemHeight</span><span style="color: #0000FF; ">=&quot;{StaticResource Size}&quot;</span><span style="color: #FF0000; "> ItemWidth</span><span style="color: #0000FF; ">=&quot;{StaticResource Size}&quot;</span><span style="color: #FF0000; "> Grid.Column</span><span style="color: #0000FF; ">=&quot;0&quot;</span><span style="color: #FF0000; "> Grid.Row</span><span style="color: #0000FF; ">=&quot;1&quot;</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">WrapPanel</span><span style="color: #0000FF; ">&gt;</span></div></pre></div></p> <p>Nello XAML, le proprietà <strong>ItemHeight</strong> e <strong>ItemWidth</strong> dello WrapPanel non sono più cablate, ma fanno riferimento alla stessa StaticResource, denominata Size. Ma dove è definita questa risorsa? Ancora una volta, non avrebbe senso definirla nello XAML, perchè in realtà il valore che ci serve deve essere reperito nel file dei settings. E allora?</p> <p>La soluzione che ho adottato è creare ed aggiungere una risorsa chiamata <strong>Size</strong> via codice, nel costruttore della classe ChooseEmoticon, che è la Window che contiene lo XAML che definisce il WrapPanel qui sopra. Il costruttore è il seguente:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:772eb7f6-ea74-44d2-8ddb-a42fcfeab6fe" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">public</span><span style="color: #000000; "> ChooseEmoticon() { initialize(); InitializeComponent(); populateIcons(); }</span></div></pre></div></p> <p>Notare la chiamata al metodo <strong>initialize()</strong>, definito come <font color="#0000ff">private</font>. Il metodo contiene...</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:bdca2b54-3577-4274-b84e-bcec243de0ac" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:White;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #0000FF; ">private</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> initialize() { </span><span style="color: #008000; ">//</span><span style="color: #008000; "> Aggiungo la risorsa ItemSize che viene poi usata dal WrapPanel </span><span style="color: #008000; ">//</span><span style="color: #008000; "> per settare ItemWidth e ItemHeight con la sintassi </span><span style="color: #008000; ">//</span><span style="color: #008000; "> {StaticResource Size}</span><span style="color: #008000; "> </span><span style="color: #000000; "> </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.Resources.Add(</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Size</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">, _settings.Size); </span><span style="color: #008000; ">//</span><span style="color: #008000; "> altro codice di inizializzazione </span><span style="color: #008000; "> </span><span style="color: #000000; ">}</span></div></pre></div></p> <p>La classe Windows espone una proprietà <strong>Resources</strong>, di tipo <strong>ResourceDictionary</strong>, attraverso la quale possiamo gestire le risorse via C#. Il codice qui sopra aggiunge una risorsa con key = "Size", ed il cui valore viene prelevato dai settings dell'utente. <strong><font color="#ff0000">Occhio che la risorsa deve essere aggiunta alla Window prima della chiamata ad InitializeComponent()</font></strong>. Lo XAML adesso può far uso di una StaticResource attraverso la sintassi ItemHeight="{StaticResource Size}". L'unico svantaggio di questo approccio è che la risorsa non è definita a design-time, e quindi l'editor di VS2005 ci segnala un errore nello XAML, proprio perchè mentre stiamo sviluppando la risorsa <strong>Size</strong> non esiste ancora. In realtà, si può sistemare anche questo...</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70628.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/13/70628.aspx Tue, 13 Feb 2007 12:36:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/13/70628.aspx#feedback 2 http://blogs.ugidotnet.org/idamiani/comments/commentRss/70628.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70628.aspx Autocritica sul mio plug-in http://blogs.ugidotnet.org/idamiani/archive/2007/02/12/70548.aspx <p>Vabbè che ho criticato <a href="http://blogs.ugidotnet.org/lbarbieri" target="_blank">Lorenzo</a> quando ho bloggato sul mio plug-in, ma una buona autocritica ogni tanto ci vuole.<br>Ci sono alcune cose che non mi piacciono del mio plug-in per Live Writer. Vediamo cosa ne pensate.</p> <ol> <li>Non mi piace (ma proprio per niente!) che le immagini delle emoticons vengano prese dal percorso <em><font color="#0000ff">C:\Program Files\Windows Live Writer\Plugins\Emoticons</font></em>. Non è il posto adatto, non è <em>user-scope</em>, sotto Vista richiede i permessi di Administrator per poterci scrivere dentro.</li> <li>In conseguenza del punto (1), vorrei utilizzare un altro percorso più adatto. Qualcosa del tipo <em><font color="#0000ff">C:\Documents and Settings\&lt;username&gt;\Local Settings\Application Data\qualcosa</font>.</em></li> <li>Vorrei poter creare sottofolder dentro il path del punto (2), che saranno navigabili dalla Window del plug-in. Questa&nbsp;dovrebbe servire&nbsp;per organizzare le emoticons per categorie (sorrisi, tristi, divertenti, etc.). I sottofolder non hanno effetto sul blocco HTML generato per inserire l'emoticon nel post in WLW.</li> <li>Il plug-in di Lorenzo permetteva di cambiare l'url del fornitore delle emoticon. Voglio farlo anche io, così ognuno di noi può mettersi le immagini da qualche parte (un proprio spazio web) le emoticons che vuole usare e farle puntare da lì.</li> <li>Hostarlo su <a href="http://www.codeplex.com/" target="_blank">CodePlex</a>.</li></ol> <p>Altre idee? Suggerimenti? Critiche? Proposte?</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70548.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/12/70548.aspx Mon, 12 Feb 2007 13:34:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/12/70548.aspx#feedback 4 http://blogs.ugidotnet.org/idamiani/comments/commentRss/70548.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70548.aspx [Parte 2] Qualche info tecnica sul mio plug-in http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70376.aspx <p>Per far capir meglio le logiche del layout di WPF, che sono molto diverse rispetto al classico Windows Forms, ho preferito elaborare questa immagine:</p> <p><img src="http://www.igordamiani.it/blog/struttura_xaml.jpg"> </p> <p>Questo&nbsp;mi sa che è&nbsp;il mio post più colorato!<img src="http://www.tuttogratis.it/img/emoticons/_hi_hi.gif" border="0">&nbsp;La window <strong>ChooseEmoticon</strong> è formata principalmente da una Grid con quattro righe, che corrispondono ai colori giallo (in alto), rosa (al centro), bianco (ehm...un po' più in basso rispetto al centro) e verde+rosso (in basso). In XAML, la dichiarazione della Window è la seguente...</p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:6c60a636-cf08-4871-80b7-9210df202ac9" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#DADAA5;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Window x:Class</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">VivendoByte.Emoticons.ChooseEmoticon</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> xmlns</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">http://schemas.microsoft.com/winfx/2006/xaml/presentation</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> xmlns:x</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">http://schemas.microsoft.com/winfx/2006/xaml</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Title</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">VivendoByte Emoticons</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Width</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">400</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Height</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">300</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> ResizeMode</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">CanResizeWithGrip</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span></div></pre></div> <p>...dove viene definito il titolo, larghezza ed altezza e la modalità di ridimensionamento. Il tag di Window si chiude in fondo allo XAML. La Grid invece appare nello XAML come segue:</p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:4e7be020-a929-43d6-a9f6-387f3c0c1a45" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#DADAA5;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Grid</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Grid.RowDefinitions</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">RowDefinition Height</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">35</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;&lt;/</span><span style="color: #000000; ">RowDefinition</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">RowDefinition Height</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;&lt;/</span><span style="color: #000000; ">RowDefinition</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">RowDefinition Height</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">25</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;&lt;/</span><span style="color: #000000; ">RowDefinition</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">RowDefinition Height</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">60</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;&lt;/</span><span style="color: #000000; ">RowDefinition</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">Grid.RowDefinitions</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> ... ... </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">Grid</span><span style="color: #000000; ">&gt;</span></div></pre></div> <p>Come si vede, la Grid ha quattro righe: alcune hanno alltezza fissa (35, 25 e 60), mentre una ha un'altezza definita come * (asterisco, star o come lo chiamate voi). Al posto dei "..." ci va un altro blocco di XAML, che definisce il contenuto della Grid (TextBlock e quant'altro).</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:bfb7f8dc-3927-4296-82fa-787604e31d57" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#DADAA5;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">TextBlock VerticalAlignment</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Center</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> FontSize</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">16</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Margin</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Row</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Column</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> Clicca sull</span><span style="color: #000000; ">'</span><span style="color: #000000; ">emoticon che vuoi inserire...</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">TextBlock</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">TextBlock Name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">emoticonsAvaiable</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> VerticalAlignment</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Center</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> FontSize</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">12</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Margin</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Row</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Column</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> Le emoticon(s) disponibili sono xxx. </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">TextBlock</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">WrapPanel Name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">MainPanel</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> ItemHeight</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">70</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> ItemWidth</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">70</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Column</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Row</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">WrapPanel</span><span style="color: #000000; ">&gt;</span></div></pre></div></p> <p>I primi due blocchi di XAML definiscono due TextBlock: uno per la scritta "<em><font color="#008040">Clicca sull'emoticon che vuoi inserire...</font></em>" ed un altro per "<em><font color="#008040">Le emoticon(s) disponibili sono xxx.</font></em>". Poi viene inserito un WrapPanel, che conterrà le emoticons: si trova nella cella (0,1) della Grid - quella ad altezza variabile. Ciò significa che quando la finestra viene ridimensionata, lo WrapPanel si ridimensiona automaticamente.&nbsp;I Children&nbsp;contenuti nello WrapPanel vengono automaticamente riposizionati (<em>arrange</em>) in base alle dimensioni correnti.</p> <p>Il blocco di XAML qui sopra determina il contenuto della prima, seconda e terza riga. La quarta riga (quella verde+rosso) è formata a sua volta da un DockPanel.&nbsp;Docckato a&nbsp;sinistra (area verde) c'è un MediaElement, che serve per fare la preview di un'emoticon. Dockkati a destra (area rossa) invece abbiamo i due Button <strong>Annulla</strong> ed <strong>Inserisci</strong>. Il blocco di XAML per fare tutto questo è il seguente:</p> <p> <div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:6727b8a4-6824-460e-b611-459351b034c3" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#DADAA5;"><div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">DockPanel Grid.Column</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Grid.Row</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">MediaElement DockPanel.Dock</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Left</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Margin</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Width</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">70</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">emoticonPreview</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;&lt;/</span><span style="color: #000000; ">MediaElement</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">StackPanel DockPanel.Dock</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Right</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Orientation</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">Horizontal</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> FlowDirection</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">RightToLeft</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Button Margin</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Width</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">70</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> IsEnabled</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">False</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> IsCancel</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">False</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> IsDefault</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">True</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">btnInsert</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Click</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">InsertEmoticon</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">Inserisci</span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">Button</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Button Margin</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Width</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">70</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> IsCancel</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">True</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; "> Name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">btnCancel</span><span style="color: #000000; ">&quot;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">Annulla</span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">Button</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">StackPanel</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "> </span><span style="color: #000000; ">&lt;/</span><span style="color: #000000; ">DockPanel</span><span style="color: #000000; ">&gt;</span></div></pre></div></p> <p>Giocando un po' con i margini, si ottiene una buona impaginazione degli elementi e dei controlli sulla finestra. Notare che ai Button vengono impostate alcune proprietà (IsEnabled, IsCancel, IsDefault e soprattutto il Name) ed un handler per l'evento Click (Button <strong>btnInsert</strong>), che si chiama <strong>InsertEmoticon</strong>. Il codice per questo handler è ovviamente definito nel code-behind, insieme ad un altro po' di roba di cui parleremo la prossima volta.</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70376.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70376.aspx Sat, 10 Feb 2007 18:36:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70376.aspx#feedback 2 http://blogs.ugidotnet.org/idamiani/comments/commentRss/70376.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70376.aspx [Parte 1] Qualche info tecnica sul mio plug-in http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70371.aspx <P>Il mio plug-in per Live Writer <A href="http://blogs.ugidotnet.org/rgm/archive/2007/02/10/70348.aspx" target=_blank>ha raccolto il suo primo fan.</A> A parte scherzi, voglio descrivervi un attimo come l'ho fatto, non perch&#232; sia particolarmente complicato, quanto perch&#232; &#232; creato in WPF e magari qualche informazione pu&#242; essere utile. Le informazioni in giro per il Web per creare un plug-in per WLW sono facilmente reperibili. Tutte ci dicono che dobbiamo ereditare dalla classe <STRONG>ContentSource</STRONG> e fare l'override del metodo <STRONG>CreateContent</STRONG>. Ed &#232; quello che ho fatto:</P><PRE><SPAN style="COLOR: teal"> 1</SPAN> [WriterPluginAttribute <SPAN style="COLOR: teal"> 2</SPAN> (<SPAN style="COLOR: maroon">"887EC618-8FBE-49a5-A908-2339AF2EC721"</SPAN>, <SPAN style="COLOR: teal"> 3</SPAN> <SPAN style="COLOR: maroon">"VivendoByte Emoticons"</SPAN>, <SPAN style="COLOR: teal"> 4</SPAN> ImagePath = <SPAN style="COLOR: maroon">"Icon.png"</SPAN>, <SPAN style="COLOR: teal"> 5</SPAN> PublisherUrl = <SPAN style="COLOR: maroon">"http://blogs.ugidotnet.org/idamiani"</SPAN>, <SPAN style="COLOR: teal"> 6</SPAN> Description = <SPAN style="COLOR: maroon">"Interfaccia WPF per inserire le tue emoticons!"</SPAN>)] <SPAN style="COLOR: teal"> 7</SPAN> [InsertableContentSourceAttribute(<SPAN style="COLOR: maroon">"VivendoByte Emoticons"</SPAN>)] <SPAN style="COLOR: teal"> 8</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">class</SPAN> EmoticonPlugin : ContentSource <SPAN style="COLOR: teal"> 9</SPAN> { <SPAN style="COLOR: teal"> 10</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">override</SPAN> DialogResult CreateContent(IWin32Window dialogOwner, <SPAN style="COLOR: blue">ref</SPAN> <SPAN style="COLOR: blue">string</SPAN> newContent) <SPAN style="COLOR: teal"> 11</SPAN> { DialogResult returned = DialogResult.Cancel; <SPAN style="COLOR: teal"> 12</SPAN> ChooseEmoticon window = <SPAN style="COLOR: blue">new</SPAN> ChooseEmoticon(); <SPAN style="COLOR: teal"> 13</SPAN> <SPAN style="COLOR: teal"> 14</SPAN> <SPAN style="COLOR: blue">bool</SPAN> ret = window.ShowDialog().GetValueOrDefault(); <SPAN style="COLOR: teal"> 15</SPAN> <SPAN style="COLOR: teal"> 16</SPAN> <SPAN style="COLOR: blue">if</SPAN> (ret) <SPAN style="COLOR: teal"> 17</SPAN> { <SPAN style="COLOR: teal"> 18</SPAN> newContent = window.ImageUrl; <SPAN style="COLOR: teal"> 19</SPAN> returned = DialogResult.OK; <SPAN style="COLOR: teal"> 20</SPAN> } <SPAN style="COLOR: teal"> 21</SPAN> <SPAN style="COLOR: teal"> 22</SPAN> <SPAN style="COLOR: blue">return</SPAN> (returned); <SPAN style="COLOR: teal"> 23</SPAN> } <SPAN style="COLOR: teal"> 24</SPAN> }</PRE> <P>Non date troppo peso alla formattazione del codice: ho utilizzato <A href="http://puzzleware.net/codehtmler/default.aspx" target=_blank>questo sito</A> per ottenere la rappresentazione HTML del codice C#. Come ci mostra l'SDK di WLW, ho utilizzato la classe <STRONG>WriterPluginAttribute</STRONG> per dare un nome al plug-in, per associare un'immagine alla voce di men&#249; che comparir&#224; dentro WLW (il file Icon.png, che &#232; definita nella soluzione VS2005 come Embedded Resource), indicare l'url di riferimento del plug-in e per dare una descrizione (visibile dal men&#249; <STRONG>Tools</STRONG> --&gt;&nbsp;<STRONG>Preferences</STRONG> --&gt; <STRONG>Plugins</STRONG>).</P> <P>Il metodo <STRONG>CreateContent</STRONG> &#232; piuttosto semplice. La cosa pi&#249; importante &#232; il secondo parametro <STRONG>newContent</STRONG>: esso &#232; una stringa che viene passata come riferimento. Ci&#242; significa, banalizzando un po', che viene ritornata all'istanza di WLW aperta. Il metodo ritorna un DialogResult: se&nbsp;dal metodo ritorniamo&nbsp;<STRONG><FONT color=#ff0000>DialogResult.Cancel</FONT></STRONG>, il valore di newContent viene ignorato. Se dal metodo ritorniamo <STRONG><FONT color=#008040>DialogResult.OK</FONT></STRONG>, il valore di newContent viene inserito nel testo del post editato in WLW. Nota: se newContent contiene codice HTML, questo codice viene inserito nel codice HTML del post. Il codice sopra istanza un oggetto ChooseEmoticon (che &#232; una Window), la visualizza sullo schermo come modale utilizzando il metodo ShowDialog() e controlla come &#232; stata chiusa la finestra:</P> <OL> <LI>se la dialog ha ritornato <STRONG>true</STRONG>, impostiamo newContent e chiudiamo il plug-in con DialogResult.OK <LI>se la dialog ha ritornato <STRONG>false</STRONG>, chiudiamo il plug-in con DialogResult.Cancel ed al post non accade nulla</LI></OL> <P>La parte che&nbsp;coinvolge WPF coinvolge la window ChooseEmoticon, che&nbsp;&#232; creata con un po' di XAML ed un po' di <EM>code-behind</EM>. La classe ChooseEmoticon deriva direttamente da Window ed aggiunge una propriet&#224; read-only, <STRONG>ImageUrl</STRONG>, che vedete nel blocco di codice sopra. Tale propriet&#224;, di tipo string, contiene una cosa del tipo:</P> <P><EM><FONT color=#008000>&lt;IMG src="http://www.tuttogratis.it/img/emoticons/{0}" border=0&gt;</FONT></EM></P> <P>Al posto di {0} finisce ovviamente il nome dell'immagine da inserire, con un semplice <STRONG>string.Format</STRONG>. Vi riporto un blocco di codice della classe ChooseEmoticon.</P><PRE><SPAN style="COLOR: teal"> 1</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">partial</SPAN> <SPAN style="COLOR: blue">class</SPAN> ChooseEmoticon : System.Windows.Window <SPAN style="COLOR: teal"> 2</SPAN> { <SPAN style="COLOR: teal"> 3</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">partial</SPAN> <SPAN style="COLOR: blue">class</SPAN> ChooseEmoticon : System.Windows.Window <SPAN style="COLOR: teal"> 4</SPAN> { <SPAN style="COLOR: teal"> 5</SPAN> <SPAN style="COLOR: blue">string</SPAN> _selectedEmoticon = <SPAN style="COLOR: blue">string</SPAN>.Empty; <SPAN style="COLOR: teal"> 6</SPAN> VivendoByteEmoticons _settings = <SPAN style="COLOR: blue">new</SPAN> VivendoByteEmoticons(); <SPAN style="COLOR: teal"> 7</SPAN> <SPAN style="COLOR: teal"> 8</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">string</SPAN> SelectedEmoticon <SPAN style="COLOR: teal"> 9</SPAN> { <SPAN style="COLOR: teal"> 10</SPAN> <SPAN style="COLOR: blue">get</SPAN> { <SPAN style="COLOR: blue">return</SPAN> _selectedEmoticon; } <SPAN style="COLOR: teal"> 11</SPAN> } <SPAN style="COLOR: teal"> 12</SPAN> <SPAN style="COLOR: teal"> 13</SPAN> <SPAN style="COLOR: blue">public</SPAN> <SPAN style="COLOR: blue">string</SPAN> ImageUrl <SPAN style="COLOR: teal"> 14</SPAN> { <SPAN style="COLOR: teal"> 15</SPAN> <SPAN style="COLOR: blue">get</SPAN> <SPAN style="COLOR: teal"> 16</SPAN> { <SPAN style="COLOR: teal"> 17</SPAN> <SPAN style="COLOR: blue">if</SPAN> (_selectedEmoticon != <SPAN style="COLOR: blue">string</SPAN>.Empty) <SPAN style="COLOR: teal"> 18</SPAN> { <SPAN style="COLOR: teal"> 19</SPAN> <SPAN style="COLOR: blue">return</SPAN> (<SPAN style="COLOR: blue">string</SPAN>.Format(_settings.ImageUrl, _selectedEmoticon)); <SPAN style="COLOR: teal"> 20</SPAN> } <SPAN style="COLOR: teal"> 21</SPAN> <SPAN style="COLOR: blue">else</SPAN> <SPAN style="COLOR: teal"> 22</SPAN> { <SPAN style="COLOR: teal"> 23</SPAN> <SPAN style="COLOR: blue">return</SPAN>(<SPAN style="COLOR: blue">string</SPAN>.Empty); <SPAN style="COLOR: teal"> 24</SPAN> } <SPAN style="COLOR: teal"> 25</SPAN> } <SPAN style="COLOR: teal"> 26</SPAN> } <SPAN style="COLOR: teal"> 27</SPAN> } <SPAN style="COLOR: teal"> 28</SPAN> }</PRE> <P>Il tutto &#232; definito come partial. E' possibile vedere la definizione delle due propriet&#224; di cui parlavo prima: ImageUrl &#232; la pi&#249; importante, perch&#232; ritorna il tag <IMG> che ho detto prima. Ho definito anche SelectedEmoticon, che invece ritorna il nome del file ("_inferm.gif") dell'emoticon correntemente selezionata.</P> <P>Nel prossimo post vedremo la definizione dello XAML della window ChooseEmoticon, come viene popolato lo WrapPanel che contiene tutti i Button, qualche handler.</P><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70371.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70371.aspx Sat, 10 Feb 2007 17:51:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/10/70371.aspx#feedback http://blogs.ugidotnet.org/idamiani/comments/commentRss/70371.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70371.aspx Inserire emoticons da Live Writer con WPF http://blogs.ugidotnet.org/idamiani/archive/2007/02/09/70274.aspx <p>Qualche giorno fa ho dato un'occhiata al plug-in di Lorenzo per inserire le emoticon da Live Writer, ma non mi è piaciuto granchè. Non ha un'anteprima dell'emoticon, perchè la ComboBox tradizionale non mostra immagini per ogni elemento inserito. Così mi sono deciso a crearne uno mio che mi piacesse di più.</p> <p>Perchè non farlo in WPF? Il risultato è questo...</p> <p><img src="http://www.igordamiani.it/blog/VivendoByteEmoticons.JPG"> </p> <p>Le emoticons sono inserite all'interno di un WrapPanel: di conseguenza, quando ridimensionate la finestra le immagini si riposizionano automaticamente. Ogni emoticon è un semplice&nbsp;Button. Sebbene le emoticons siano GIF animate, nei Button viene mostrato solo il primo frame, altrimenti è quasi <em>psichedelico</em> vedere decine e decine di animazioni tutte in movimento. Se volete vedere l'anteprima, cliccate su un emoticon ed essa vi apparirà in basso a sinistra. Per inserire un'emoticon, o ci fate sopra doppio-click oppure cliccare sull'emoticon e poi sul pulsante Inserisci. L'url che viene inserito punta al sito <a href="http://www.tuttogratis.it">www.tuttogratis.it</a>, che è il sito dal quale provengono le emoticon.</p> <p><a href="http://www.igordamiani.it/download.php?id=16" target="_blank"><strong>Il plug-in è liberamente scaricabile da qui</strong></a>.</p> <p>Il file zip va decompresso dentro <em><font color="#0000ff">C:\Program Files\Windows Live Writer\Plugins</font></em>. Esso contiene l'assembly <em><font color="#0000ff">VivendoByteEmoticons.dll</font></em> e una directory <em><font color="#0000ff">Emoticons</font></em> che contiene tutti i files GIF delle emoticons che servono per le preview. Se volete aggiungere le vostre, basta copiarle dentro questa directory. Fatemi sapere se vi piace... :-) Magari scrivo un altro post più tecnico - oddio, non che ci sia molto di tecnico, però magari qualche dritta interessante c'è...</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/70274.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/02/09/70274.aspx Fri, 09 Feb 2007 14:56:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/02/09/70274.aspx#feedback 5 http://blogs.ugidotnet.org/idamiani/comments/commentRss/70274.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/70274.aspx PostSpeedometer : plugin per Windows Live Writer http://blogs.ugidotnet.org/idamiani/archive/2007/01/19/67724.aspx <p>Questa mattina ho buttato giù l'idea, ma dando un'occhiata ai vari post, non è poi così dispendioso creare un plug-in per WLW funzionale e divertente. C'è una limitazione, però, che avrete notato anche voi se usate qualche plug-in: ogni plug-in è accessibile attraverso il menù <strong>Insert</strong> di WLW. Scordatevi, per esempio, di&nbsp;inserire emoticon come faceva IMHO. Questi intercettava stringhe come ":-)" e le sostituiva con la sintassi HTML che invece inseriva l'immagine. Qui le cose sono diverse, perchè bisogna sempre passare dal menù <strong>Insert</strong>.</p> <p>Detto questo, vediamo di buttare giù un po' di idee per il mio plug-in e di condividerle con voi.</p> <p><strong>Cosa voglio ottenere dal plug-in?</strong><br>Ho un problema: voglio che alla fine del mio post venga riportato un piccolo blocco di testo che mi dice:</p> <ol> <li>a che ora ho cominciato a scrivere il post</li> <li>a che ora ho finito di scrivere il post</li> <li>l'intervallo di tempo trascorso</li> <li>la velocità media in caratteri/secondo con cui ho scritto il post</li></ol> <p>Quindi, l'utente apre WLW, va su <strong>Insert</strong> e poi clicca su <strong>Post Speedometer</strong>, una voce di menù nuova inserita dal mio plug-in. Il primo click su questo menù salva in una variabile il DateTime.Now, dietro previa conferma. Se dice OK, infatti, la misurazione della velocità comincia e non c'è più scampo. :-)</p> <p>L'utente scrive il post e, indipendentemente da quanto è lungo, alla fine deve ritornare a cliccare su <strong>Insert</strong> e poi su <strong>Post Speedometer</strong>. Il plug-in rileva nuovamente il DateTime.Now, sottrae questo valore a quello iniziale, ottenendo in questo modo un TimeSpan. Posso quindi segnalare all'utente quanto ci ha messo a scrivere il post.</p> <p><strong>Houston,&nbsp;abbiamo un problema!<br></strong>Per calcolare la velocità mi manca un dato fondamentale, ovvero <strong><font color="#ff0000">il numero di caratteri scritti nel post</font></strong>. Mi pare che l'object model non esponga questa informazioni, ma ci guardo ancora un po', poi devo fare altro.</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/67724.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2007/01/19/67724.aspx Fri, 19 Jan 2007 15:51:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2007/01/19/67724.aspx#feedback 3 http://blogs.ugidotnet.org/idamiani/comments/commentRss/67724.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/67724.aspx [HappySign] Brainstorming - idee per inizio 2007 http://blogs.ugidotnet.org/idamiani/archive/2006/12/29/63934.aspx <p>Tra un bug-fixing e l'altro, i check-in di <a href="http://www.codeplex.com/HappySign" target="_blank">Happy Sign</a> si fanno sentire. Gli ultimi changeset non sono stati corposi in termini di <em>numero di files modificati</em>, ma sono stati essenziali per eliminare alcune superficiali imperfezioni. L'attuale sorgente di <a href="http://www.codeplex.com/HappySign" target="_blank">Happy Sign</a> su CodePlex è piuttosto stabile - l'aggettivo "<em>stabile</em>" risulta da un'analisi del mio utilizzo quotidiano di Happy Sign. ;-)</p> <p><strong>Ultima feature implementata: "disponibilità di una DynamicSignature"</strong><br>L'ultima feature interessante apportata in Happy Sign è stata implementata dal buon&nbsp;Matteo. E' stata&nbsp;aggiunta una proprietà <strong>Enabled</strong> alla classe DynamicSignature, che indica la disponibilità di una firma. Cosa intendiamo&nbsp;con il termine&nbsp;<em>disponibilità</em>? E' semplice: <strong><font color="#0000ff">una firma è disponibile quando il codice .NET associato è valido</font></strong>, è compilabile e può produrre un assembly. Quando una firma è disponibile, l'utente può utilizzarla (tramite drag'n'drop o clipboard) e&nbsp;può esportarla: può fare tutto quello che vuole.<br><strong><font color="#ff0000">Se il codice .NET non è valido</font></strong>, è sintatticamente scorretto, non può essere compilato, gli manca qualche reference, allora la firma non è disponibile. Una firma non disponibile appare comunque sulla UI di Happy Sign, ma viene evidenziata da un'icona di avviso. L'utente non può usarla, non può esportarla, fino a quando non sistema il codice. :-)</p> <p><strong>Alcune idee per il futuro</strong><br>Nonostante tutto quello che abbiamo fatto, le idee per l'anno prossimo sono davvero tante. Le elenco qui in breve.</p> <ol> <li><strong><font color="#0000ff">Utilizzo di una cache per migliorare le prestazioni</font></strong><br>Quando si decide di utilizzare una DynamicSignature, <font color="#ff0000">l'engine di Happy Sign compila on-the-fly il codice .NET</font>, genera un file HappySignScript.dll nella directory privata dell'utente. Inutile dire che c'è un leggero gap di tempo, dove con <em>gap</em> si intende un intervallo di tempo proporzionale alla complessità del codice da compilare. Onestamente, questo attualmente non rappresenta un grande problema, ma non mi piace questo tipo di approccio. L'obiettivo è quello di avere una cache privata, dove vengono salvati tutti gli assembly. In breve: se ho una firma chiamata "Il mio prossimo compleanno", dalla sua compilazione (scatenata la prima volta che verrà usata) risulterà un assembly chiamato IlMioProssimoCompleanno.dll. Se l'utente decide di usare&nbsp;in futuro&nbsp;questa firma dinamica, non verrà scatenata ogni volta una nuova compilazione, ma verrà sfruttata direttamente la dll in cache. La cache deve essere aggiornata ogni volta che si modifica il codice: su questo stiamo lavorando. <li><strong><font color="#0000ff">Ordinare firme e categorie</font><br></strong>Nell'attuale release, le categorie possono essere riordinata a piacimento, mentre le firme no. Abbiamo intenzione di dare all'utente la possibilità di ordinare secondo diversi criteri: alfabetico, frequenza di utilizzo, data di ultima modifica (sono i primi che mi vengono in mente). <li><strong><font color="#0000ff">Parametri delle firme</font></strong><br>Questo è un bel problemino. Supponiamo di aver creato una DynamicSignature che ritorna il numero di giorni che mancano al mio compleanno. Nel codice .NET associato alla firma avremo messo una variabile DateTime impostata sul nostro giorno di nascita. La firma va che è una meraviglia, decido di esportarla e di distribuirla. Arriva l'utente Piero, si importa la firma, la utilizza ma i conti non tornano, perchè nel codice è cablata la data di nascita dell'autore. L'utente Piero dovrebbe andare nel codice e correggere la data mettendo la sua. Brutto, non vi pare? Su questo siamo in alto mare - accettiamo idee &amp; suggerimenti. :-) <li><strong><font color="#0000ff">Varie ed eventuali</font></strong><br>Chissà quante cose adesso non mi vengono in mente.</li></ol> <p>Lunga vita ad Happy Sign! :-)</p> <h5><em>[Mancano 61 giorni al mio compleanno. Ricordatevelo!]<br>Powered by Happy Sign - <a href="http://www.codeplex.com/HappySign">http://www.codeplex.com/HappySign</a></em></h5><img src="http://blogs.ugidotnet.org/idamiani/aggbug/63934.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2006/12/29/63934.aspx Fri, 29 Dec 2006 17:42:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2006/12/29/63934.aspx#feedback http://blogs.ugidotnet.org/idamiani/comments/commentRss/63934.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/63934.aspx [HappySign] Secondo webcast, stavolta per sviluppatori http://blogs.ugidotnet.org/idamiani/archive/2006/12/04/58412.aspx <p>Scaricatelo qua : <a href="http://www.igordamiani.it/download.php?id=7" target="_blank">link diretto al webcast</a>&nbsp;(durata circa 30 minuti, 22Mb in formato WMV)</p> <p>Sabato pomeriggio, sul tardi, ho trovato il tempo per parlare da solo davanti al PC per circa 30 minuti, realizzando il mio secondo webcast dedicato ad <strong><a href="http://www.codeplex.com/HappySign" target="_blank">Happy Sign</a></strong>. I temi espressi questa volta erano rivolti agli sviluppatori: ho preparato persino delle slides (che pubblico domani), manco fosse un webcast "serio". :-))&nbsp;Chi ha seguito il mio blog nei giorni scorsi, sentirà parlare di cose già trattate: <strong>SignatureBase</strong>, <strong>NormalSignature</strong> e <strong>DynamicSignature</strong>, che sono i mattoncini fondamentali su cui si appoggia l'attuale versione di Happy Sign. Ma con la mia voce, è tutta un'altra cosa! Bisogna vedere se è in meglio o in peggio. ;-)</p> <p>C'è una bella e semplice spiegazione sull'interfaccia <strong>IHappySignScript</strong>, che è l'interfaccia che tutte le firme dinamiche devono implementare, che prevede la creazione di un metodo <strong>GetValueParameter</strong>. Maggiori dettagli qua ve li risparmio, <a href="http://www.igordamiani.it/download.php?id=7" target="_blank">guardate il mio webcast</a>. Ho aggiunto qualcosa su come unirsi al team su CodePlex (registrazione, Team Explorer, etc.) e&nbsp;qualcosa sulle prossime modifiche. Personalmente, valuto positivamente questo mio secondo esperimento: la prima volta ero quasi imbarazzato davanti al mio PC (sebbene fossi da solo per avere più tranquillità), mi ero preparato una scaletta piuttosto rigida da seguire, avevo una voce più "emozionata", quasi. Sabato invece sono andato più liscio: senza scaletta, quasi improvvisando, ed in certi punti si sente anche, perchè perdo un po' il filo del discorso. Il bello della diretta! :-)</p> <p>Sono contento di essere riuscito a farlo, perchè questa settimana starò lontano dal PC e sparirò dalla circolazione fino a lunedì prossimo. Ho fatto vedere il video in anteprima a qualcuno del team, che l'hanno giudicato positivamente, ma giustamente con qualche critica ed osservazione. Ne aprofitto per correggere qualche imprecisione apparsa nel webcast.</p> <p><strong>Le firme dinamiche devono essere per forza nella categoria "Dinamiche C#" ?<br></strong>Durante il webcast, creo diverse firme dinamiche come demo, inserendole tutte all'interno della categoria "Dinamiche C#". Questa cosa non è assolutamente obbligatoria: potete creare categorie nella più completà libertà, con il nome che volete, e potete inserire al loro interno ogni tipo di firma. Quello che faccio durante il webcast è puramente casuale!</p> <p><strong>Ehm...Igor, il menù dalla tray-bar da dove salta fuori?<br></strong>Rispetto all'ultimo webcast, Happy Sign ha subìto diversi miglioramenti della UI. Tra queste, anche la comparsa di un&nbsp;menù contestuale (classe ContextMenuStrip) raggiungibile dalla tray-bar. Ne ho parlato <a href="http://blogs.ugidotnet.org/idamiani/archive/2006/11/24/57147.aspx" target="_blank">in questo post</a>, ma magari qualcuno si chiede da dove salti fuori. Questo menù permette agli utenti di poter utilizzare le firme senza avere Happy Sign sullo schermo, ma semplicemente ridotto ad icona. Le modalità per utilizzare le firme sono attualmente tre: 1) il più figo: il <em>drag'n'drop</em> 2)&nbsp;<em>cliccando col destro sulla firma attraverso clipboard</em>&nbsp;e 3) il <em>menù dalla tray-bar</em>.</p> <p>Se lo vedete/ascoltate, mi dite cosa ne pensate?</p> <p>Scaricatelo qua : <a href="http://www.igordamiani.it/download.php?id=7" target="_blank">link diretto al webcast</a>&nbsp;(durata circa 30 minuti, 22Mb in formato WMV)</p><img src="http://blogs.ugidotnet.org/idamiani/aggbug/58412.aspx" width="1" height="1" /> Igor Damiani http://blogs.ugidotnet.org/idamiani/archive/2006/12/04/58412.aspx Mon, 04 Dec 2006 13:00:00 GMT http://blogs.ugidotnet.org/idamiani/archive/2006/12/04/58412.aspx#feedback http://blogs.ugidotnet.org/idamiani/comments/commentRss/58412.aspx http://blogs.ugidotnet.org/idamiani/services/trackbacks/58412.aspx