Guida al Visual Basic .NET
Capitolo 97° - Utilizzo avanzato della classe Graphics
Penne alternative
Nel capitolo precedente abbiamo impiegato penne predefinite. Ora vogliamo cercare qualcosa di più accattivante. Dopo aver inizializzato un nuovo oggetto Pen, possiamo modificarne le proprietà:
Pennelli alternativi
Oltre a SolidBrush, esistono alcuni altri pennelli con caratteristiche peculiari. Ad esempio:
Esempio 1: Creare una userbar
Per mostrarvi qualche utilizzo pratico e non proprio basilare alla grafica in .NET voglio mostrare come sia possibile disegnare una userbar
simile a quelle create con Photoshop.
Noi automatizzeremo tutto questo creando una classe apposita: Namespace Userbars Class Userbar Private _BackgroundImage As Image Private _BackgroundImagePosition As Int32 Private _Text As String Private _Size As Size = New Size(350, 25) Public Property Size() As Size Get Return _Size End Get Set(ByVal value As Size) If value.Width > 0 And value.Height > 0 Then _Size = value Else _Size = New Size(350, 25) End If End Set End Property Public Property BackgroundImage() As Image Get Return _BackgroundImage End Get Set(ByVal value As Image) If value.Width > Me.Size.Width Or value.Height > Me.Size.Height Then Throw New ArgumentOutOfRangeException() Else _BackgroundImage = value End If End Set End Property Public Property BackgroundImagePosition() As Int32 Get Return _BackgroundImagePosition End Get Set(ByVal value As Int32) If value > Me.Size.Width Then Throw New ArgumentOutOfRangeException() Else _BackgroundImagePosition = value End If End Set End Property Public Property Text() As String Get Return _Text End Get Set(ByVal value As String) _Text = value End Set End Property Public Function Create() As Image Dim Result As New Bitmap(Me.Size.Width + 1, Me.Size.Height + 1) Dim G As Graphics = Graphics.FromImage(Result) 'Questi valori sono statici poiché costanti. Una 'volta inizializzati saranno sempre uguali e non 'verranno creati ulteriori oggetti ad ogni invocazione 'di Create() 'HatchBrush permette di riempire un'area con una trama 'prefissata. Noi vogliamo disegnare delle sottili righe 'scure, un motivo a cui corrisponde l'enumeratore 'indicato. 'Il colore usato è un Nero con opacità pari 'a 48: dato che il valore massimo è 255, si tratta di 'un nero al 19% di opacità. Il colore di sfondo è 'invece trasparente (come se non ci fosse). Static LinesBrush As New HatchBrush(HatchStyle.DarkUpwardDiagonal, Color.FromArgb(48, Color.Black), Color.Transparent) 'Il font usato è Visitor TT2 BRK, grandezza 11pt. '11 va molto bene per le userbar di dimensione 'standard. Se volete qualcosa di più generale, 'il font deve dipendere dall'altezza Static FontUsed As New Font("Visitor TT2 BRK", 11, FontStyle.Regular) 'Questo pennello servirà per l'effetto lucido. Dato 'che si tratta di un SolidBrush, riempirà l'area con 'un colore omogeneo, in questo caso un bianco 'trasparente Static TranspBrush As New SolidBrush(Color.FromArgb(70, Color.White)) 'Imposta la modalità di smussamento delle linee. Dato 'che questa funzione viene usata solo quando l'utente 'la richiede (quindi non molte volte al secondo), e che 'il risultato deve essere il migliore possibile, 'utilizziamo un algoritmo ad alto rendimento e 'bassa velocità di rendering. G.SmoothingMode = SmoothingMode.HighQuality 'Imposta la modalità di sovrapposizione. Poiché 'dobbiamo disegnare molte cose le una sopra alle altre, ci 'serve che i nuovi disegni non sovrascrivano quelli 'precedenti, ma vi si applichino sopra rispettandone 'le trasparenze G.CompositingMode = CompositingMode.SourceOver 'Disegna l'immagine di sfondo G.DrawImage(Me.BackgroundImage, Me.BackgroundImagePosition, 0) 'Disegna le righe su tutta l'immagine G.FillRectangle(LinesBrush, 0, 0, Me.Size.Width, Me.Size.Height) 'Applica il velo di bianco trasparente. Notate che 'utilizzo delle coordinate negative per disegnare 'l'ellisse fuori dall'immagine. In questo modo, 'noi vedremo solo la parte di ellisse che rientra 'nell'area effettivamente esistente, ossia solo metà. 'Inoltre ho messo qualche coefficiente per aggiustare 'la larghezza e rendere migliore l'aspetto G.FillEllipse(TranspBrush, -5, -Me.Size.Height + 3, Me.Size.Width + 10, CInt(Me.Size.Height * 1.5)) 'Disegna il contorno della barra G.DrawRectangle(Pens.Black, 0, 0, Me.Size.Width, Me.Size.Height) 'Calcola la dimensione del testo (in pixel) Dim TextSize As SizeF = G.MeasureString(Me.Text, FontUsed) 'Quindi disegna la stringa Text in bianco, spostata 'rispetto al margine destro in modo che il testo non 'vada fuori dall'immagine. G.DrawString(Me.Text, FontUsed, Brushes.White, Me.Size.Width - CInt(TextSize.Width) - 30, Me.Size.Height 3) 'Restituisce il risultato Return Result End Function End Class End Namespace
Ed ecco un esempio:
Esempio 2: Orologio analogico
Ecco uno stupidissimo codice di esempio per disegnare un orogoloio: Class Form1 Private ClockImage As New Bitmap(230, 230) Private G As Graphics = Graphics.FromImage(ClockImage) Private Sub tmrClock_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrClock.Tick G.Clear(Me.BackColor) Dim Time As Date = Date.Now Static BorderPen As New Pen(Color.Black, 5) Static HourPen As New Pen(Color.Red, 4) With {.EndCap = LineCap.Triangle} Static MinutePen As New Pen(Color.Blue, 2) With {.EndCap = LineCap.Triangle} Static SecondPen As New Pen(Color.Green, 1) Dim C As Point = New Point(ClockImage.Width / 2, ClockImage.Height / 2) Dim h, m, s As Single h = Time.Hour + (Time.Minute / 60) m = Time.Minute + (Time.Second / 60) s = Time.Second G.SmoothingMode = SmoothingMode.AntiAlias G.FillEllipse(Brushes.White, 5, 5, ClockImage.Width - 10, ClockImage.Height - 10) G.DrawEllipse(BorderPen, 5, 5, ClockImage.Width - 10, ClockImage.Height - 10) For I As Int32 = 0 To 11 G.FillEllipse(Brushes.Black, _ C.X + CInt(ClockImage.Width / 2.3 * Math.Cos(Math.PI / 2 - I / 6 * Math.PI)) - 1, _ C.Y - CInt(ClockImage.Width / 2.3 * Math.Sin(Math.PI / 2 - I / 6 * Math.PI)) - 1, _ 2, 2) Next G.DrawLine(HourPen, C.X, C.Y, _ C.X + CInt(ClockImage.Width / 4 * Math.Cos(Math.PI / 2 - h / 6 * Math.PI)), _ C.Y - CInt(ClockImage.Width / 4 * Math.Sin(Math.PI / 2 - h / 6 * Math.PI))) G.DrawLine(MinutePen, C.X, C.Y, _ C.X + CInt(ClockImage.Width / 3 * Math.Cos(Math.PI / 2 - m / 30 * Math.PI)), _ C.Y - CInt(ClockImage.Width / 3 * Math.Sin(Math.PI / 2 - m / 30 * Math.PI))) G.DrawLine(SecondPen, C.X, C.Y, _ C.X + CInt(ClockImage.Width / 2.2 * Math.Cos(Math.PI / 2 - s / 30 * Math.PI)), _ C.Y - CInt(ClockImage.Width / 2.2 * Math.Sin(Math.PI / 2 - s / 30 * Math.PI))) imgClock.Image = ClockImage End Sub End Class
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|