Riprendo un mio post precedente in cui disegnavo un rettangolo con gli angoli arrotondati per aggiungere un paio di cosette.
La formettina di esempio diventa la seguente:
Il primo obiettivo è di gestire lo zoom.
Per prima cosa mettiamo una variabile per il valore dello zoom ed un componente trackBar in alto a sinistra per impostarne quel valore nel suo evento Scrool:
Private _zoom As Single = 1.0
Private Sub TrackBar1_Scroll(...) Handles TrackBar1.Scroll
' Cambia lo zoom
Me._zoom = Me.TrackBar1.Value / 5
' Ridisegna
Me.PictureBox1.Invalidate()
End Sub
Nell'esempio del mio post precedente avevo definito 2 funzioni, una per il disegno del rettangolo ed una per la griglia: le 2 funzioni venivano chiamate nel gestore dell'evento Paint della PictureBox. Ora modifichiamo il gestore per gestire lo zoom:
Private Sub PictureBox1_Paint(...) Handles PictureBox1.Paint
Try
' Recupera l'oggetto Graphics
Dim g As Graphics = e.Graphics
' Cambia lo zoom
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.ScaleTransform(Me._zoom, Me._zoom)
' Disegna la griglia
DrawGrid(g)
[...]
' Disegna il rettangolo
DrawRoundedRectangle(g, p, rect, cornerSize)
[...]
A questo punto il gioco è fatto e qualcunque cosa si disegli sull'oggetto graphics viene zoommata automaticamente.
Resta però un problema, ovvero cosa succede degli eventi del mouse sulla PictureBox?
Gli eventi vengono generati nelle coordinate della PictureBox, per cui se volessimo gestire gli eventi di MouseDown/Move/Up per consentire all'utente di disegnare linee libere dovremmo convertire le coordinate del mouse sulla PictureBox nelle coordinate del disegno su cui è applicato lo zoom.
Definiamo quindi la seguente semplice funzione di conversione:
''' <summary>
''' Converte le coordinate di un punto sullo schermo nelle coordinate
''' del disegno, in base allo zoom corrente
''' </summary>
Public Function ZoomTransformPointToDraw(ByVal pointOnPictureBox As Point) As Point
If Me._zoom > 0 Then
Return New Point(pointOnPictureBox.X / Me._zoom, pointOnPictureBox.Y / Me._zoom)
Else
Return New Point(pointOnPictureBox.X, pointOnPictureBox.Y)
End If
End Function
A questo punto registriamo i punti in cui passa il mouse, convertiti tramite la funzione di sui sopra. In pratica avremo il gestore dell'evento di MouseDown che fa qualcosa tipo:
Private Sub PictureBox1_MouseMove(...) Handles PictureBox1.MouseMove
Dim p As Point = New Point(e.X, e.Y)
' Converte le coordinate di un punto
p = Me.ZoomTransformPointToDraw(p)
If e.Button = Windows.Forms.MouseButtons.Left And _mouseClicked Then
' Aggiunge il punto alla lista di quelli da disegnare
_puntiCorrenti.Add(p)
' Ridisegna
Me.PictureBox1.Invalidate()
End If
End Sub
Non rimane che gestire il MouseDown ed il MouseUp per la registrazione dei punti, che verranno salvati in delle liste:
Private Sub PictureBox1_MouseDown(...) Handles PictureBox1.MouseDown
_mouseClicked = True
_puntiCorrenti = New List(Of Point)
Dim p As Point = New Point(e.X, e.Y)
p = Me.ZoomTransformPointToDraw(p)
_puntiCorrenti.Add(p)
_puntiTotali.Add(_puntiCorrenti)
End Sub
Private Sub PictureBox1_MouseUp(...) Handles PictureBox1.MouseUp
_mouseClicked = False
End Sub
Oltre che del flag _mouseClicked avremo bisongo delle variabili _puntiCorrenti e _puntiTotali:
Private _mouseClicked As Boolean = False
Private _puntiTotali As New List(Of List(Of Point))
Private _puntiCorrenti As List(Of Point)
... il tutto verrà disegnato nel gestore dell'evento Paint della PictureBox, che quindi diventa:
Private Sub PictureBox1_Paint(...) Handles PictureBox1.Paint
Try
' Recupera l'oggetto Graphics
Dim g As Graphics = e.Graphics
' Cambia lo zoom
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.ScaleTransform(Me._zoom, Me._zoom)
' Disegna la griglia
DrawGrid(g)
[...]
' Disegna il rettangolo
DrawRoundedRectangle(g, p, rect, cornerSize)
' Disegna i punti liberi
Dim path As GraphicsPath
Dim _punti As List(Of Point)
For i As Integer = 0 To _puntiTotali.Count - 1
_punti = _puntiTotali(i)
path = New GraphicsPath()
path.AddLine(_punti(0), _punti(0))
For j As Integer = 0 To _punti.Count - 2
path.AddLine(_punti(j), _punti(j + 1))
Next
g.DrawPath(p, path)
path.Dispose()
path = Nothing
Next
Catch ex As Exception
[...]
End Try
End Sub
Ed ecco il risultato (in cui ho scritto "ciao!" avendo lo zoom al 160%):