Diamo forma personalizzata e colori trasparenti alle nostre finestre con VB.NET : gli shaped form

Molte applicazioni presentano finestre con forme stravaganti e bordi trasparenti, realizzare una cosa del genere con VB.NET è una cosa piuttosto semplice. Abbiamo innanzitutto bisogno di un’immagine che dovrà fungere da sfondo per la nostra finestra, rigorosamente in formato GIF o PNG (da scartare le JPG che a causa della compressione possono presentare artefatti che inficerebbero l’effetto trasparenza o le BMP a causa della memoria occupata). L’immagine deve essere disegnata in maniera tale da avere un’area (ovvero quella che vogliamo sia invisibile) di un colore uniforme, un’immagine del genere disegnata con photoshop è l’ideale:

immagine_per_shaped_form

Come vedete l’area intorno alla stella è colorata in maniera uniforme (tenete a mente il codice esadecimale del colore utilizzato, in questo caso è  FF00FF). Nulla ci vieta di utilizzare immagini al posto di forme come in questo caso, l’importante (per ottenere un certo impatto visivo) è quello di fare in modo che lo sfondo sia di un colore uniforme e soprattutto non utilizzato nel resto dell’immagine (ovviamente se abbiamo un’immagine al cui interno ci sono aree bianche e lo sfondo che vogliamo rendere trasparente è bianco, si otterranno degli effetti antiestetici, dal momento che tutto ciò che nell’immagine è bianco viene reso trasparente). Per questo motivo spesso (soprattutto nelle GIF animate) viene sempre scelto il colore FF00FF, perchè difficilmente tale colore è presente nell’immagine.

Avviamo quindi una nuova applicazione Windows Forms, per dare forma a un Form (scusate l’inevitabile cacofonìa) abbiamo bisogno principalmente di settare soltanto 3 proprietà:

  • FormBorderStyle
    Deve essere impostata su “None” , in maniera da non avere bordi intorno al Form
  • BackgroundImage
    ovvero l’immagine di sfondo del form, che possiamo importare come risorsa locale o risorsa del progetto
  • TransparencyKey
    che ci permette di impostare il colore trasparente. In questo caso tale proprietà verrà impostata direttamente nel metodo Load del form:

    Me.TransparencyKey = System.Drawing.Color.FromArgb(255, 0, 255)

    (da notare che il codice del colore trasparente da esadecimale: FF00FF è stato convertito in RGB: 255,0,255)

Fatto questo dobbiamo quindi settare larghezza e altezza del form per fare in modo che l’immagine entri tutta, e impostare la proprietà BackColor dei vari controlli su Transparent e il più è fatto. Il risultato, utilizzando belle immagini, è di sicuro effetto:

shaped_form_demo

Ovviamente anche se il contorno del form è invisibile, è ancora sensibile.

Avviando l’applicazione in modalità debug però ci accorgiamo da subito di 2 problemi: Il form, mancando del bordo non può essere spostato, il form non può essere chiuso.

Per quanto riguarda la questione della chiusura, il sistema è semplice, possiamo mettere un pulsante o una label che lanciano il metodo Close, io personalmente in un form del genere preferisco piuttosto gestire il doppio click per effettuarne la chiusura.

Per lo spostamento, invece, dobbiamo ricorrere ad un artifizio: gestire gli eventi MouseDown, MouseUp e MouseMove sul form e su qualsiasi altro oggetto sul quale l’utente può cliccare senza problemi (ad esempio eventuali label non associate a nessuna funzione).

Il codice utilizzato è il seguente:

Public Class formMain
 
    ' Variabili utilizzate per gestire il drag
    Dim DragEnabled As Boolean
    Dim MouseX As Integer
    Dim MouseY As Integer
 
    Private Sub formMain_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown, Label1.MouseDown
 
        ' Click sul form o sulla Label1
 
        ' Imposto la mia variabile di controllo
        DragEnabled = True
 
        ' Recupero la posizione attuale del mouse
        MouseX = Windows.Forms.Cursor.Position.X - Me.Left
        MouseY = Windows.Forms.Cursor.Position.Y - Me.Top
 
    End Sub
 
    Private Sub formMain_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove, Label1.MouseMove
 
        ' Se la mia variabile di controllo è impostata su vero
        ' muovo il form insieme al mouse
 
        If DragEnabled Then
 
            Me.Top = Windows.Forms.Cursor.Position.Y - MouseY
            Me.Left = Windows.Forms.Cursor.Position.X - MouseX
 
        End If
 
    End Sub
 
    Private Sub formMain_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp, Label1.MouseUp
 
        ' Rilascio del mouse sul form o sulla label 1
        ' Imposto su Falso la mia variabile di controllo
        DragEnabled = False
 
    End Sub
 
' ... resto del codice
 
End Class

In pratica la soluzione come si vede è molto elementare, viene settata una variabile globale (DragEnabled) su Vero quando viene effettuato il click sul form o su un altro elemento inutilizzato (Label1 nel nostro esempio), in questo istante viene anche memorizzata la posizione del mouse. Quando il mouse viene mosso, si scatena l’evento associato per cui il form viene spostato in contemporanea (il movimento del form viene effettuato soltanto se la nostra variabile di controllo è vera), quando il mouse viene rilasciato, la variabile di controllo viene resettata, altrimenti il form continuerebbe a muoversi.

Su MSDN, in questa pagina,  c’è un esempio simile, che utilizza un altro codice per il movimento del form.

In allegato il progetto completo : [download#24]

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)