Francesco Geri

Il blog di Francesco Geri
posts - 94, comments - 165, trackbacks - 2

Disegnare con GDI+: gestire lo zoom

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:

image

 

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%):

 

image

Print | posted on giovedì 11 settembre 2008 03:23 | Filed Under [ .Net GDI+ ]

Powered by:
Powered By Subtext Powered By ASP.NET