Site:  Cours VB.net  
E 4.3 Exemples:Dessin avec souris

 

Un source très simple très didactique, pour dessiner avec la souris:

 

On appuie sur le bouton de la souris, on déplace la souris: cela dessine un trait.

Si on clique sur les boutons Rouge, Vert, Bleu cela change la couleur du trait.

Comment faire?

Dans Form1 on crée :

Une PictureBox définissant la zone de dessin: PictureBox1

Les boutons ButtonRouge, ButtonVert, ButtonBleu ayant dans leur propriété text respectivement 'Rouge', 'Vert', 'Bleu'.

Au niveau de la Classe on crée les variables ThePen de type Pen contenant la couleur en cours et PreviousPoint de type Point qui désigne le dernier point ou était la souris.

Les évènements Click des boutons ButtonRouge, ButtonVert, ButtonBleu modifie la couleur en cours:
ThePen.Color = Color.Blue

Le dessin est effectué par les procédures évènement de la souris:

MouseDown enregistre le précédent Point (les coordonnées de la souris sont fournis par le paramètre e, ce sont e.X et e.Y)

MouseMove: On teste si la souris est 'capturée' sur le PictureBox (c'est à dire si on est en glissé: déplacement de la souris bouton appuyé, cela donne à PictureBox1.Capture la valeur True).

Si la souris est capturée:

If PictureBox1.Capture Then

On récupère le Graphics de PictureBox1:

Dim NewGraphic As Graphics = PictureBox1.CreateGraphics()

On trace sur le graphics une ligne du PreviousPoint au Point actuel avec ThePen:

 NewGraphic.DrawLine(ThePen, PreviousPoint, NewPoint)

On détruit le graphics, puis on met dans PreviousPoint le point actuel.

 

Cela donne:

Imports System.Drawing

 

Public Class Form1

Inherits System.Windows.Forms.Form

 

Private PreviousPoint As Point ' Dernier point de la souris

Private ThePen As New System.Drawing.Pen(Color.Red) 'Un Pen pour dessiner.

 

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown

Dim NewPoint As New Point(e.X, e.Y)

PreviousPoint = NewPoint

End Sub

 

 

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove

If PictureBox1.Capture Then

Dim NewPoint As New Point(e.X, e.Y)

Dim NewGraphic As Graphics = PictureBox1.CreateGraphics()

NewGraphic.DrawLine(ThePen, PreviousPoint, NewPoint)

NewGraphic.Dispose()

PreviousPoint = NewPoint

End If

End Sub

 

 

Private Sub ButtonRouge_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRouge.Click

ThePen.Color = Color.Red

End Sub

 

Private Sub ButtonVert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonVert.Click

ThePen.Color = Color.Green

End Sub

 

Private Sub ButtonBleu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonBleu.Click

ThePen.Color = Color.Blue

End Sub

End Class

 

Dans une version VB6 de ce programme, je n'utilisais pas Capture, aussi j'utilisais une variable Globale 'Tracer': MouseDown lui donnait la valeur True, MouseUp la valeur False et dans MouseMove on traçait si 'Tracer' était à True.

Mais c'est plus facile avec Capture.

Problème:

Si une fenêtre est positionnée sur notre fenêtre de dessin puis enlevée, le dessin disparaît!!

En VB6, la propriété AutoRedraw de l'image permettait de rappeler automatiquement le BitMap du dessin et de faire réapparaître l'image, cela n'existe plus en VB.Net!!

A- On peut écrire une nouvelle méthode OnPaint de l'image (on la substitue grâce à Overrides), elle est déclenchée à chaque fois que le contrôle est redessiné; on y met du code qui redessine (forme géométrique..).

Exemple afficher une ligne dans une form, qui restera affichée même si on redimensionne.

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

Dim myPen As New System.Drawing.Pen(System.Drawing.Color.Red)

Dim formGraphics As System.Drawing.Graphics

formGraphics = Me.CreateGraphics()

formGraphics.DrawLine(myPen, 0, 0, 200, 200)

myPen.Dispose()

formGraphics.Dispose()

End Sub

 

 mais dans notre programme à moins d'enregistrer dans un tableau les coordonnées et couleur de chaque point puis de les redessiner un à un, ce n'est pas possible.

B- Comment faire l'équivalent de l'autoRedraw?

Class Form1

Private PreviousPoint As Point ' Dernier point de souris

Private ThePen As New System.Drawing.Pen(Color.Red)

Private MyBitMap As Bitmap = New Bitmap(200, 200) 'Je crée un BitMap

Private NewPoint As New Point 'point actuel

 

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown

NewPoint = New Point(e.X, e.Y)

PreviousPoint = NewPoint

End Sub

 

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove

If PictureBox1.Capture Then

Dim NewPoint As New Point(e.X, e.Y)

Dim newgraphic As Graphics = Graphics.FromImage(MyBitMap) 'je crée un Graphics à partir du BitMap

newgraphic.DrawLine(ThePen, PreviousPoint, NewPoint)      'je dessine sur le Graphics 

PictureBox1.Image = MyBitMap                              'je passe le BitMap dans le PictureBox1 

 

PreviousPoint = NewPoint

End If

End Sub

 

End Class

 

 

Quand on crée un Graphics depuis un contrôle comme dans la première version, le graphics ne pointe pas sur la propriété image mais sur son affichage à l'instant T. Ce n'est pas mémorisé.

Beaucoup de contrôles .net ont une propriété image. A chaque rafraîchissement du contrôle si un bitMap est "attaché" à la propriété, le fond du contrôle est affiché automatiquement. Le picturebox est le plus simple de ces contrôles ... il ne fait que ça.

Donc en fait pour dessiner sur un contrôle (quel qu'il soit) tu n'as que 2 possibilités :

- Redessiner tout à chaque fois dans l'évènement Onpaint
- Lui affecter une image de fond et travailler sur celle ci