venerdì 26 febbraio 2010

Appunti di WPF – Terza Puntata – Hello World!

In questo tutorial vediamo come creare la nostra prima applicazione WPF.

Apriamo Visual Studio 2010, scegliamo “New Project” dalla schermata iniziale (o dal menù File->New Project) e selezioniamo il progetto di tipo “WPF Application”:

WPF_03_HelloWorld_Fig1

Digitiamo il nome del progetto HelloWorld al posto di WpfApplication1 e premiamo Ok per far si che Visual Studio 2010 crei l’infrastruttura del progetto:

WPF_03_HelloWorld_Fig2
Vediamo in dettaglio quali file vengono creati da Visual Studio e la loro funzione nel nostro progetto. L’elenco dei file del progeto è riportato all’interno della finestra Solution Explorer:

WPF_03_HelloWorld_Fig3

· Application.xaml : è il file xaml dell’applicazione in cui viene definita quale è la finestra principale e vengono definite le risorse dell’applicazione;

· Application.xaml.vb : è il file di codice che definisce la classe dell’applicazione. In questo file può essere inserito del codice per gestire gli aventi dell’applicazione come lo startup o lo shutdown;

· MainWindow.xaml : è il file xaml che definisce la finsetra principale dell’applicazione;

· MainWindow.xaml.vb : è il file di codice della finestra principale (code behind).

Facciamo doppio click sul file MainWindow.xaml per aprire, al centro della finestra di Visual Studio 2010, la finestra di progettazione dell’interfaccia xaml:

WPF_03_HelloWorld_Fig4 
La finestra è divisa in due sezioni:

· Design : mostra il layout dell’interfaccia che stiamo creando;

· XAML : mostra il codice XAML della finestra.

Proviamo, ora, ad aggiungere un bottone alla nostra finestra.

Tra le finestre messe a disposizione da Visual Studio troviamo la finestra degli strumenti:

WPF_03_HelloWorld_Fig5

Portiamo il mouse al di sopra dell’oggetto Button e tenendo premuto il tasto sinistro del mouse trasciniamolo al di sopra della finestra che stiamo progettando e rilasciamo il tasto sinistro.

Otteniamo, in questo modo, che il bottone viene inserito all’interno dell’interfaccia:

WPF_03_HelloWorld_Fig6

Innanzitutto osserviamo che trascinare il bottone sull’interfaccia fa si che il designer inserisca un tag Button all’interno del file XAML. In particolare osserviamo che vengono definite anche alcune proprietà del controllo Button, tra cui altezza, larghezza, margini, nome e allineamento del testo. Un ruolo particolare riveste la proprietà Content che rappresenta ciò che verrà visualizzato all’interno del bottone. Vedremo nei tutorial successivi che il Content (così come altre proprietà) può essere un qualsiasi oggetto .NET (anche complesso).

Per migliorare l’interfaccia modifichiamo le proprietà del bottone nel seguente modo:

  1. <Button Content="Premi" Height="50"
  2.         HorizontalAlignment="Left" Margin="202,130,0,0"
  3.         Name="btnPremi" VerticalAlignment="Top"
  4.         Width="100" />

A questo punto gestiamo la pressione del tasto btnPremi. Per fare ciò è sufficiente fare doppio click al di sopra del pulsante nella finestra di design. Questa operazione crea, come accadeva anche nella progettazione delle Windows Forms, un gestore di evento per l’evento Click del pulsante nel code behind della finestra. Completiamo il gestore di eventi nel seguente modo:

  1. Private Sub btnPremi_Click(ByVal sender As System.Object,
  2.                            ByVal e As System.Windows.RoutedEventArgs) Handles btnPremi.Click
  3.     MessageBox.Show("Hello World!!")
  4. End Sub

La nostra applicazione è, dunque, pronta per essere testata. Premiamo F5 e premiamo il tasto Premi nel momento in cui appare la nostra finestra:

WPF_03_HelloWorld_Fig7


Scarica la solution per Visual Studio 2010 Scarica la versione PDF dell'articolo. Scarica la versione Amazon Kindle dell'articolo.

mercoledì 24 febbraio 2010

Appunti di WPF – Seconda Puntata – L’architettura di WPF

In questo tutorial analizzeremo l’architettura di WPF, cioè quali sono i building blocks costitutivi del framework di Windows Presentation Foundation.

La seguente immagine mostra lo schema architetturale di WPF:

WPF_02_Architettura_Fig1

Analizziamo i singoli componenti che fanno parte del framework:

· PresentationFramework.dll : contiene i tipi WPF di alto livello (windows, pannelli e altri controlli) e i tipi astratti di programmazione dell’interfaccia grafica come, ad esempio, i tipi astratti per la definizione degli stili;

· PresentationCore.dll : contiene i tipi base di WPF come, ad esempio, UIElement e Visual dai quali derivano tutti i controlli;

· WindowsBase.dll : contiene tutte quelle classi che possono, in linea teorica, essere riutilizzate al di fuori dell’ambiente WPF (come, ad esempio, DispatcherObject e DependencyObject);

· Milcore.dll : rappresenta il nucleo del sistema di rendering di WPF e la parte più importante del Media Integration Layer (MIL). E’ questo il componente che si occupa di tradurre i componenti di alto livello (contenuti nel livello delle API Managed) negli oggetti comprensibili dalle API di DirectX. Questo componente è considerato all’interno dello stack architetturale di WPF anche se è parte integrante di Windows Vista;

· WindowsCodecs.dll : contiene le API di basso livello per la gestione delle immagini;

· Direct3D, User32 : sono i componenti del sistema operativo.

Tutto il lavoro grafico di WPF viene, alla fine dei conti, realizzato da Direct3D.

Compresi quali sono i componenti costituenti il framework WPF, diamo un’occhiata a quale è la gerarchia delle classi fondamentali degli oggetti grafici.

La seguente figura illustra la gerarchia fondamentale degli oggetti:

WPF_02_Architettura_Fig2

Vediamo le caratteristiche di ogni classe:

· DispatcherObject : Analogamente a quanto accade per le Windows Forma, anche le applicazioni WPF utilizzano il modello Single-Thread Affinity (STA). Questo significa che i controlli dell’interfaccia utente sono “posseduti” da un solo thread e non è possibile accedere a tali controlli da un altro thread. La gestione di questo modello di threading è demandata ad un oggetto Dispatcher che si occupa di gestire i messaggi di sistema (pressione dei tasti, movimento del mouse, etc., etc.). Gli elementi che derivano da DispatcherObject hanno la capacità di verificare se il codice sta “girando” nel thread corretto o no e di utilizzare il Dispatcher per permette al codice di gestire i controlli nel thread corretto;

· DependencyObject : In WPF le proprietà degli oggetti giocano un ruolo fondamentale perché sono i membri delle classi che possono subire il binding dei dati, interagire con le animazioni nell’interfaccia grafica e molto altro. Tra le funzionalità più importanti abbiamo la possibilità di utilizzare le Dependency Properties (di cui parleremo approfonditamente in un altro tutorial) la cui gestione viene implementata in questa classe;

· Visual : Ogni elemento che compare in una interfaccia grafica WPF è un oggetto che deriva da Visual. La classe Visual rappresenta la classe astratta di una qualsiasi entità disegnabile, incapsula le funzionalità di disegno, ulteriori dettagli su come il disegno deve essere eseguito e altre funzionalità di base. La classe Visual fornisce il punto di giunzione tra la libreria in codice Managed di WPF e le primitive presenti all’interno della libreria milcore.dll;

· UIElement : La classe UIElement fornisce le funzionalità di base per il layout, input, il focus e gli eventi. In questa classe viene gestito lo spostamento del mouse, la pressione dei tasti e così via. In questa classe viene gestito anche il supporto ai comandi;

· FrameworkElement : La classe FrameworkElement implementa effettivamente dei membri che sono definiti in UIElement;

· Shape : E’ la classe base per le figure geometriche;

· Panel : E’ la classe base di tutti i contenitori di oggetti di WPF;

· Control : La classe Control rappresenta un qualsiasi controllo che può interagire con l’utente in termini di eventi del mouse, della tastiera, etc., etc. Questa classe fornisce il supporto ai Template.

· ContentControl : E’ la classe base dei controlli che hanno contenuto composto da un singolo elemento (bottoni, textbox, etc., etc). Questo singolo contenuto può essere un qualsiasi oggetto, anche complesso, realizzato componendo elementi di interfaccia.

· ItemsControl : E’ la classe base di tutti i controlli che contengono una collezione di elementi.


Scarica la versione PDF dell'articolo. Scarica la versione Amazon Kindle dell'articolo.

lunedì 22 febbraio 2010

Appunti di WPF – Prima Puntata – Introduzione a WPF

Con questo post vorrei iniziare una serie di “appunti” sulla tecnologia WPF. Si tratta di articoli preparati per la community DotNetRomaCestà che attualmente ha chiuso il proprio portale e che, quindi, non potranno essere, almeno nell’immediato, pubblicati. Ho, quindi, deciso di pubblicarli su questo blog con la speranza che a qualcuno possano essere utili. Non hanno la pretesa di essere esaustivi ma di mostrare alcune caratteristiche di WPF a coloro che si avvicinano alla tecnologia.

Fino all’introduzione di WPF (avvenuta nella versione 3.0 del Framework) gli sviluppatori hanno utilizzato, per realizzare le interfacce grafiche, tecnologie vecchie di circa 15 anni.

Si tratta di User32 e GDI/GDI+:

· User32 : una serie di API che forniscono il look and feel che tutti conosciamo (bottoni, finestre, etc., etc.);

· GDI/GDI+ : fornisce il supporto alla grafica 2D come figure, testo o immagini.

Entrambe le tecnologie sono state introdotte con il sistema operativo Windows 3.0 agli inizi degli anni 90 (di cui rappresentano due dei componenti core) e nel corso degli anni sono state raffinate e migliorate con i successivi sistemi operativi usciti.

Tutti i framework applicativi usciti dopo l’introduzione dei due componenti, hanno realizzato dei wrapper delle API fornite da questi fino all’introduzione di WPF che ha, invece radicalmente cambiato il modo di pensare l’interfaccia grafica e di interagire con il sistema operativo e, soprattutto, con l’hardware della macchina.

Il mattone sui cui si basa questo cambio epocale è l’introduzione di DirectX (avvenuta con Windows 95 OSR2/ NT4.0 alla fine del 1994) che fornisce una serie di API per la gestione della grafica che interagiscono con le schede grafiche utilizando le potenzialità che quest’ultime mettono a disposizione nelle attività per cui sono create: fare grafica!

Proprio l’utilizzo delle potenzialità delle schede grafiche fornisce la chiave per rendere le applicazioni più veloci, scalabili e con effetti grafici difficilmente realizabili (se non addirittura) impensabili con le tecnologie User32/GDI.

WPF utilizza, dunque, DirectX per tutta l’infrastruttura grafica abbandonando, in questo modo, GDI e GDI+. In realtà, WPF continua ad utilizzare alcuni servizi messi a disposizione da User32 (ad esempio la gestione dell’input dell’utente) ma tutta la parte grafica viene ridiretta verso le API DirectX.

WPF mette a disposizione le funzionalità di DirectX (wrapando la difficoltà intrinseca dell’utilizzo della API native) ma non fa solo questo. Le peculiarità di WPF possono essere riassunte in queste caratteristiche:

· Modello di layout tipo web : nella programmazione classica delle windows forms siamo abituati a posizionare i controlli in base alle coordinate della finestra (in termini di pixel). In WPF il posizionamento dei controlli dell’interfaccia grafica può avvenire in maniera relativa come accade per i controlli all’interno di una web form. Questo tipo di posizionamento favorisce il ridimensionamento delle finestre della nostra applicazione;

· Modello di disegno : WPF fornisce della classi che ci consentono di disegnare oggetti (forme, linee, testo, etc., etc.) all’interno della nostra interfaccia grafica;

· Modello di testo : WPF fornisce, inoltre, un object model molto ricco per la manipolazione del testo e la visualizzazione dello stesso all’interno di un’interfaccia grafica. L’insiame delle classi per la gestione del testo garantisce una migliore leggibilità e ridimensione del testo all’interno delle nostre applicazioni;

· Animazioni : le animazioni costitiuscono un sottoinsieme dell’object model di WPF, il che significa che tutto ciò che concerne l’animazione di un qualsiasi oggetto grafico all’interno dell’interfaccia grafica è rapresentabile come classi del Framework e, come vedremo in seguito, a livello di definizione dell’interfaccia stessa;

· Audio e Video : WPF fornisce classi per la gestione del’audio e del video che ci consentono di integrare completamente i contenuti multimediali all’interno della nostra interfaccia;

· Stili e template : Anche per questa funzionalità, WPF si è ispirata al mondo web ed ha introdotto, a livello di client stand-alone, il concetto di stile e template di un controllo grafico. Questo consente di descrivere, a livello di definizione dell’interfaccia, in che modo un controllo appare a video. I controlli non sono più delle scatole nere dal punto di vista del rendering ma possono essere manipolati a nostro piacimento;

· Comandi : WPF mette a disposizione una gestione dei comandi dell’utente molto più razionale e astratta rispetto alle windows form;

· Interfaccia dichiarativa : L’interfaccia grafica di WPF viene definita utilizzando un linguaggio di mark-up (come accade per le pagine web form) che ci consente di disaccoppiare la parte di rendering grafico dalla parte di logica applicativa vera e propria. Inoltre utilizzando un linguaggio di mark-up è possibile generare l’interfaccia tramite programmi di disegno (ad esempio Expression Blend) o esportare la grafica da software di terze parti.

Scarica la versione PDF dell'articolo. Scarica la versione Amazon Kindle dell'articolo.

 

mercoledì 17 febbraio 2010

Presentato Windows Mobile 7

Vi segnalo il seguente post di MSDN

http://blogs.msdn.com/italy/archive/2010/02/15/windows-phone-7-series.aspx

in cui viene annunciata la presentazione di Windows Mobile 7.

Ci sono alcuni video interessanti tra cui la keynote di presentazione.

Technorati Tag: ,

giovedì 11 febbraio 2010

Briciole di WPF: Istanziare classi con XAML

XAML è un linguaggio dichiarativo, un dialetto dell’XML, che permette di istanziare oggetti dichiarando cosa vogliamo e con quali proprietà.

Quando scriviamo:

  1. <Button Margin="5" Content="Premi">
  2. </Button>

stiamo indicando all’interprete XAML che vogliamo un’istanza della classe Button con la proprietà Margin pari a “5” e la proprietà Content pari a “Premi”.

Di fatto, quando l’interprete XAML incontra il nodo XML di cui sopra, esegue una serie di istruzioni, esattamente equivalenti a:

  1. Dim button = New Button
  2. button.Margin = New Thickness(5)
  3. button.Content = "Premi"

Tralasciando per un attimo l’utilizzo dei TypeConverter di cui abbiamo già parlato in un precedente post, e che consente all’interprete di valorizzare le proprietà delle classi, possiamo osservare che il ragionamento fatto per la classe Button può essere esteso a qualsiasi classe che abbia:

  • un costruttore senza parametri
  • delle proprietà che possono essere assegnate a partire da una stringa tramite un opportuno TypeConverter

Supponiamo creare una classe:

  1. Public Class MiaClasse
  2.  
  3.     Public Property Intero As Integer
  4.  
  5.     Public Overrides Function ToString() As String
  6.         Return String.Format("MiaClasse Intero={0}", Me.Intero)
  7.     End Function
  8. End Class

da voler utilizzare all’interno di una nostra finestra WPF.

Innanzitutto abbiamo la necessità di importare l’assembly contenente la nostra classe (che si trova nello stesso progetto dello XAML ma che, in ogni modo, va referenziato come namespace nello XAML stesso). Per fare questo basta aggiungere la definizione del namespace all’interno del nodo Windows:

Referenziare il namespace della nostra WPF A questo punto, possiamo utilizzare il prefisso m indicato nella dichiarazione xmlns per indicare l’istanza della nostra classe.

Ad esempio possiamo scrivere:

  1. <Label>
  2.     <Label.Content>
  3.         <m:MiaClasse Intero="2"></m:MiaClasse>
  4.     </Label.Content>
  5. </Label>

In questo caso stiamo dicendo all’interprete di istanziare un oggetto di classe MiaClasse e di utilizzarlo nel content della Label. Poiché la nostra classe non deriva da UIElement, verrà richiamato il metodo ToString() (che abbiamo provveduto a ridefinire nella classe MiaClasse)  ed otteniamo:

Label con la nostra classe come contentE’ evidente che l’esempio riportato è puramente didattico ma ci consente di capire che XAML ha delle potenzialità che vanno oltre il mero aspetto grafico.

mercoledì 10 febbraio 2010

Release Candidate di Visual Studio 2010 per tutti

Come già segnalato in un post di ieri, da oggi è disponibile per tutti il download della Release Candidate di Visual Studio 2010.

Potete scaricarla dal link:

http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx

Buon divertimento!!!!

martedì 9 febbraio 2010

Rilasciato Visual Studio 2010 RC per gli abbonati MSDN

Brian Harry (inchino ) ha annunciato (qui il post) il rilascio della versione RC di Visual Studio 2010 per gli abbonati MSDN. Da mercoledì prossimo dovrebbe essere disponibile per tutti.

domenica 7 febbraio 2010

Software per ipovedenti gratuito

Vi segnalo una notizia apparsa sul sito di DotNetRomaCestà:

http://www.dotnetromacesta.org/Notizie.aspx?IdNews=106

Si tratta della nuova versione di Vivo 3 portatile, un programma unico ed in italiano che far parlare il computer, molto utile per le persone che hanno difficoltà di lettura.

Si tratta di un programma che non necessita di installazione. E, poi, è italiano!!!

Accessorio di SnagIT per Team System

Vorrei segnalarvi il seguente accessorio per SnagIT che permette di catturare un’immagine dallo schermo (come fa normalmente SnagIT) e di inserirla all’interno di Visual Studio Team System.

Maggiori indicazioni sulla pagina di download dell’accessorio:

http://www.techsmith.com/snagit/accessories/teamsystem.asp

o nella guida PDF scaricabile dalla stessa pagina.

Interessante post di Lorenzo Barbieri sul Blog MSDN

Vorrei segnalarvi un interessante post di Lorenzo Barbieri sul Blog MSDN relativo allo stato dell’arte dell’ALM:

http://blogs.msdn.com/italy/archive/2010/02/05/riflessioni-sui-trend-nei-sistemi-di-gestione-del-codice-sorgente.aspx

Decisamente interessante.

giovedì 4 febbraio 2010

Briciole di WPF : Le risorse incorporate

In WPF, come accade in Windows Form, possiamo incorporare delle risorse (immagini, file sonori, video, etc, etc.) all’interno di un assembly.

La modalità con cui eseguiamo questa operazione è però più vicina al mondo web che non al mondo delle Windows Forms. Per poter inserire un file di risorse all’interno di un nostro assembly è sufficiente creare una o più cartelle all’interno del progetto e, quindi, inserirvi i file da includere come risorse. Per finire è sufficiente che tali file abbiamo la proprietà Build Action impostata su Resource.

Ad esempio, nel seguente progetto abbiamo incorporato 6 immagini e un file audio:

Progetto con risorse incorporate

Nelle Windows Forms, invece, incorporiamo le risorse aggiungendole al file Resources.resx.

Nel caso precedente, nel momento in cui compiliamo, le risorse vengono inserite nell’assembly come stream di byte. Per verificare questo, possiamo aprire l’assembly con le risorse tramite Reflector:
 Le risorse incorporateOsserviamo la presenza di un oggetto memory stream per ogni file di risorsa incorporato. 

Per poter estrarre ed utilizzare le risorse all’interno del nostro codice abbiamo due strade.

La più complessa è quella di creare degli oggetti di classe UnmanagedMemoryStream come nel seguente pezzo di codice in cui estraiamo lo stream relativo alla risorsa “smile.png”:

  1. Dim imageStream As UnmanagedMemoryStream
  2. Dim resourceName = "AssemblyResource.g"
  3. Dim rm As New ResourceManager(resourceName, asm)
  4. Using resSet = rm.GetResourceSet(CultureInfo.CurrentCulture, True, True)
  5.     Dim obj = resSet.GetObject("images/smile.png", True)
  6.     imageStream = CType(obj, UnmanagedMemoryStream)
  7. End Using

Questa modalità è simile a quella che si ottiene utilizzando il metodo GetManifestResourceStream() e, come questa, nasconde la difficoltà di utilizzare uno stream di dati.

Fortunatamente WPF ci mette a disposizione un metodo molto più semplice per referenziare delle risorse incorporate, un metodo che sa molto di web.

A livello di XAML basta scrivere:

  1. <Image Source="images/smile.png"></Image>

Quindi la nostra risorsa è recuperabile con un URI (di tipo relativo) sullo stile delle immagini dei siti web.

Il meccanismo precedente è utilizzabile anche per le risorse presenti in un assembly esterno. In questo caso la sintassi è del tipo:

  1.  
  2. <Image Source="ResourceLib;component/images/sun.png" />

Anche dal punto di vista del code behind di WPF, possiamo impostare la proprietà Source di un controllo image tramite un URI:

  1. Me.Image.Source = New BitmapImage(
  2.                         New Uri("images/smile.png",
  3.                                 UriKind.Relative))

In download potete trovare una semplice solution di Visual Studio 2010 in cui mostro come effettuare il caricamento di un’immagine da una serie di risorse utilizzando l’uri:

Applicazione WPF con le risorse incorporate

lunedì 1 febbraio 2010

Briciole di WPF: Finestre non rettangolari, WPF vs Windows Forms

Questa briciola vuole mettere in evidenza il completo supporto alla trasparenza presente in WPF.

Nel fare questo effettueremo un confronto con il supporto fornito nelle Windows Forms nella creazione di finestre non rettangolari.

Partiamo da WPF. Creare finestre non rettangolari in WPF è assolutamente banale. Prendiamo ad esempio il seguente XAML:

  1. <Window x:Class="MainWindow"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     Title="MainWindow" Height="350" Width="525" Background="Transparent" WindowStyle="None" AllowsTransparency="True" MouseLeftButtonDown="Window_MouseLeftButtonDown">
  5.     <Canvas>
  6.         <Canvas.Background>
  7.             <ImageBrush ImageSource="./images/Drawing.png"></ImageBrush>
  8.         </Canvas.Background>
  9.         <Button Canvas.Top="91" Canvas.Left="100" Height="31" Width="70" Click="Button_Click">Premi</Button>
  10.         <TextBlock Canvas.Left="258" Canvas.Top="165" Height="30" Name="TextBlock1" Width="175" TextAlignment="Center" FontSize="20"/>
  11.     </Canvas>
  12. </Window>

L’immagine utilizzata come sfondo per il canvas principale è un’immagine con la trasparenza (nel nostro caso un png).
Per fare in modo che la Window supporti completamente la trasparenza è necessario:

  1. Impostare il backgroung della window a Trasparent: 
         Background="Transparent"
  2. Impostare lo stile della finestra senza i bordi e la caption:
         WindowStyle="None"
  3. Ed attivare la trasparenza:
         AllowsTransparency="True"

In particolare, se impostiamo la proprietà AllowsTransparency a true, è fondamentale impostare la proprietà WindowStyle a None, altrimenti otteniamo un errore in fase di esecuzione.

In questo modo, otteniamo una finestra con una forma non rettangolare, ma non abbiamo la possibilità di spostare la finestra, in quanto non è presente la caption.

Esempio di finestra non rettangolare

Per poter attivare lo spostamento della finestra cliccando su qualsiasi punto della finestra e trascinando la stessa è sufficiente scrivere il seguente codice come gestore dell’evento MouseLeftButtonDown:

  1. Private Sub Window_MouseLeftButtonDown(ByVal sender As System.Object, _
  2.                                        ByVal e As System.Windows.Input.MouseButtonEventArgs)
  3.     Me.DragMove()
  4. End Sub

Grazie ai routed events di WPF, la finestra viene spostata anche se ci posizioniamo con il mouse su qualsiasi controllo della nostra interfaccia che non gestisce il MouseLeftButtonDown. Nella solution che riporto nel download in fondo al post abbiamo un textblock e un button: possiamo spostare la finestra se clicchiamo sul textblock ma non sul bottone (quest’ultimo ha il gestore dell’evento click).

Vediamo, ora, come realizzare la stessa interfaccia con una windows forms. Le tecniche che si possono utilizzare per realizzare una form non rettangolare con Windows Forms sono sostanzialmente due: disegnando tramite le classi Drawing la region dell’interfaccia grafica nel metodo OnPaint della finestra  oppure, più semplicemente, impostando nel seguente modo le proprietà della finestra:

  1. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  2.     Me.BackgroundImage = New Bitmap(My.Resources.Drawing, New Size(Me.Width, Me.Height))
  3.     Me.FormBorderStyle = FormBorderStyle.None
  4.     Me.TransparencyKey = Color.FromArgb(0, 255, 255)
  5. End Sub

In questo caso la nostra immagine è presente nelle risorse del progetto (ma potrebbe essere letta anche da file) ed ha un colore scelto da noi (celeste (0,255,255) in questo caso) per indicare la parte di finestra trasparente.

Il risultato è una finestra di questo tipo:

Windows Forms non rettangolareIl problema nasce quando vogliamo abilitare il trascinamento della finestra da parte dell’utente. In questo caso dobbiamo simulare ciò che accade quando è presente la caption e l’utente è in grado di cliccare con il mouse al di sopra della stessa e trascinare l’intera finestra tenendo premuto il tasto sinistro del mouse.

Per fare questo dobbiamo utilizzare P/Invoke ed importare le seguenti funzioni:

  1. <DllImport("user32.dll")> _
  2. Private Shared Function SendMessage( _
  3.                 ByVal hWnd As IntPtr, _
  4.                 ByVal Msg As UInteger, _
  5.                 ByVal wParam As IntPtr, _
  6.                 ByVal lParam As IntPtr) As IntPtr
  7. End Function
  8.  
  9. <DllImport("user32.dll")> _
  10. Private Shared Function ReleaseCapture() As Boolean
  11. End Function
  12.  
  13. Const WM_NCLBUTTONDOWN As UInteger = &HA1
  14. Const HTCAPTION As Integer = 2

Potete trovare maggiori riferimenti alle API utilizzate ai seguenti link: SendMessage e ReleaseCapture.

Utilizziamo queste API contenute nella user32.dll per simulare le azioni che esegue l’utente al di sopra della caption della finestra nel momento in cui decide di spostarla:

  1. Private Sub MoveWindow()
  2.     Dim lngReturnValue As IntPtr
  3.     Call ReleaseCapture()
  4.     lngReturnValue = SendMessage(Me.Handle, WM_NCLBUTTONDOWN, New IntPtr(HTCAPTION), New IntPtr(0))
  5. End Sub

Utilizziamo questa funzione all’interno del gestore di evento mousemove della form e di tutti i controlli che non hanno interazione diretta con l’utente (nel nostro caso la label).

  1. Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
  2.             Handles Me.MouseMove
  3.     If e.Button = System.Windows.Forms.MouseButtons.Left Then
  4.         MoveWindow()
  5.     End If
  6. End Sub
  7.  
  8. Private Sub TextBlock1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
  9.             Handles TextBlock1.MouseMove
  10.     If e.Button = System.Windows.Forms.MouseButtons.Left Then
  11.         MoveWindow()
  12.     End If
  13. End Sub

In definitiva possiamo osservare che, per sua natura intrinseca WPF ci consente di realizzare la form non rettangolare agendo semplicemente nello XAML e sfruttando le caratteristiche di trasparenza dei formati grafici, inoltre ci semplifica la vita nella gestione del drag and drop della finestra non costringendoci all’utilizzo di P/Invoke (che tra le altre cose rende l’applicazione poco portabile).