C#2 (csharp 2) : dessiner avec gdi+ (partie 2)

I. Introduction au gdi avec c#2

Voici la suite de ce tutorial sur GDI+. La première partie traitait sommairement de la couleur, des stylos, des brosses et de l'objet Graphics.

Dans cette seconde partie nous allons pratiquer un peu à partir d'un exemple simple.

II. Explications

2.1 - Dessiner un rectangle

Commencez par créer un projet application Windows que vous nommez GDI_Bases_2. Dans la fenêtre propriétés de Form1 cherchez WindowState et mettez la à Maximized afin qu'elle occupe tout l'écran au lancement.

Faites ensuite un clic droit sur Form1 et choisissez Afficher le code. Ajoutez l'espace de nom System.Drawing.Drawing2D :

tuto csharp gdi image 1

Nous allons faire en sorte qu'un rectangle soit dessiné dans la forme lors de son ouverture. Retournez sur Form1.cs[Design] et dans la fenêtre propriétés affichez les évènements (l'icône en forme d'éclair) :

tuto csharp gdi image 2

Double cliquez sur L'évènement Load pour afficher le code correspondant. Comme nous voulons afficher un rectangle; commençons par créer un objet rectangle. En cours de saisie Intellisense nous propose les différents contructeurs. Nous choisissons le 3ème qui nous permet de préciser le coin supérieur gauche (x et y), la largeur (width) et la hauteur (height) :

tuto csharp gdi image 3

Complétez le code ainsi :

tuto csharp gdi image 4

Nous avons d'abord notre objet rectangle (40 et 40 désignent l'emplacement de son coin supérieur gauche, le premier 200 sa largeur et le second sa hauteur) qui est en fait un carré de 200 pixels sur 200 :

Rectangle rectangle = new Rectangle(40, 40, 200, 200);

Nous créons ensuite notre objet Graphics :

Graphics graphic = CreateGraphics();

Il faut comprendre que graphic est un objet attaché à la Form1 : il est l'afficheur graphique de Form1 et ne peut dessiner que dans celle-ci. Le code suivant, équivalent, traduit bien cela par l'utilisation du this. qui désigne Form1 :

Graphics graphic = this.CreateGraphics();

Nous demandons ensuite à notre objet graphic de dessiner un rectangle (DrawRectangle) en utilisant un nouveau stylo (new Pen) de couleur tomate (Color.Tomato) et d'une épaisseur de 4 pixels. En second paramètres nous passons notre objet rectangle préalablement créé :

graphic.DrawRectangle(new Pen(Color.Tomato, 4), rectangle);

Nous aurions pu écrire également :

graphic.DrawRectangle(new Pen(Color.Tomato, 4), 40, 40, 200, 200);

40, 40, 200, 200 sont les paramètres de notre rectangle, ce qui nous dispensez de créer d'abord un objet rectangle.

Et enfin nous libérons l'objet graphic en fin d'utilisation :

graphic.Dispose();

Appuyez sur F5 pour lancer le projet et admirez le résultat (bon d'accord ce n'est pas encore du Dali :) ) :

tuto csharp gdi image 5

En 4/5 lignes de code vous venez de créer votre premier dessin. Simple.....mais il y a un problème : réduisez la fenêtre de l'application et rétablissez-la : notre rectangle n'est plus là. En effet les dessins ainsi créés ne sont pas persistants, contrairement aux contrôles tels que les boutons ou cases à cocher par exemple :

tuto csharp gdi image 6

2.2 - L'évènement Paint

Windows détecte bien le problème mais ne fait rien pour raffraichir l'affichage, sinon que de signaler un évènement Paint qu'il nous faut gérer.

En gros, la méthode Paint est appelée à chaque fois que notre fenêtre d'application doit être redessinée. Windows se charge de redessiner les fenêtres et leurs contrôles mais laisse le soin à Paint de faire le reste, redessiner le rectangle dans notre cas.

Cela veut dire que nous devons dessiner dans l'évènement Paint mais aussi qu'à tout moment nous devons savoir ce qu'il y a à redessiner. Dans notre exemple c'est assez simple (un rectangle dont les paramètres sont dans le code), mais dans la pratique si le rectangle est créé en fonction de paramètres fixés par l'utilisateur, il faudrait stocker ceux-ci dans des champs de la fenêtre par exemple et les lire lors de l'évènement Paint.

Il faut également savoir que nous ne pouvons pas appeler Paint. Seul Windows le peut. Pour déclencher cet évènement nous devons invalider la zone à rafraichir par appel de la méthode Invalidate().

Revenons à la pratique pour mieux appréhender ces points.

Nous voulons donc toujours afficher un rectangle au chargement de Form1 mais nous désirons également que la méthode Paint le redessine si nécessaire.

Commencez par créer le code de l'évènement Paint en double cliquant sur celui-ci dans la fenêtre propriété de Form1 :

tuto csharp gdi image 7

Nous avons généré l'évènement Form1_Paint car notre rectangle se trouve dans cet objet. Si nous l'avions dessiné dans un autre objet (par exemple un Panel d'un SplitContainer), c'est le Paint de cet objet que nous aurions appelé.

L'argument e contient un objet Graphics déjà prêt. Il est donc inutile d'en créer un comme nous l'avions fait précédemment en appelant CreateGraphic. Dans Paint on appelle les méthodes de dessin ainsi (cas adapté à notre exemple bien sûr) :

e.Graphics.DrawRectangle(new Pen(Color.Tomato, 4), rectangle);

Modifiez le code de la façon suivante :

tuto csharp gdi image 8

Nous avons d'abord déclaré notre rectangle en variable globale afin que Paint puisse également l'utiliser.

Dans la méthode Load nous nous contentons de signaler que Form1 doit être raffraichie par this.Invalidate().

Ceci a pour conséquence d'appler Paint à qui nous demandons de dessiner notre rectangle. En réalité ce code est ici inutile car Paint est automatiquement appelé lors du chargement de la forme. Par contre il serait indispensable si l'affichage du rectangle se faisait après un clic sur un bouton (il faudrait mettre ce Invalidate() dans l'évènement Clic du bouton.

Faites F5, réduisez puis restaurez la fenêtre : notre rectangle est toujours affiché.

III. Conclusion du tutorial

Cette 2ème partie est terminée, merci d'avoir pris la peine de lire jusqu'à la fin. Je pense que vous avez désormais le minimum vital pour explorer les possibilités du GDI+ . A vous de jouer.