1.1 Les composants en général
1.2 Les contrôles sur un formulaire
1.3 Influence de la propriété parent sur l'affichage visuel d'un contrôle
1.4 Des graphiques dans les formulaires avec le GDI+
1.5 Le dessin doit être persistant
1.6 Deux exemples de graphiques sur plusieurs contrôles
- méthode générale pour tout redessiner
- des dessins sur événements spécifiques
1. Les contrôles et les fonds graphiques
Nous renvoyons le lecteur à la documentation du constructeur pour la manipulation de l'interface du RAD qu'il aura choisi. Nous supposons que le lecteur a aquis une dextérité minimale dans cette manimulation visuelle (déposer des composants, utiliser l'inspecteur d'objet (ou inspecteur de propriétés), modidifer des propriétés, créer des événements. Dans la suite du document, nous portons notre attention sur le code des programmes et sur leur comportement.
Car il est essentiel que le lecteur sache par lui-même écrire le code qui sera généré automatiquement par un RAD, sous peine d'être prisonnier du RAD et de ne pas pouvoir intervenir sur ce code !
1.1 les composants en général
System.Windows.Forms.Control définit la classe de base des contrôles qui sont des composants avec représentation visuelle, les fiches en sont un exemple.
System.Object
System.MarshalByRefObject
System.ComponentModel.Component
System.Windows.Forms.Control
System.Windows.Forms.ScrollableControl
System.Windows.Forms.ContainerControl
System.Windows.Forms.Form
Dans les deux RAD Visual C# et C#Builder la programmation visuelle des contrôles a lieu d'une façon très classique, par glisser déposer de composants situés dans une palette ou boîte d'outils. Il est possible de déposer visuellement des composants, certains sont visuels ils s'appellent contrôles, d'autres sont non visuels, ils s'appellent seulement composants.
Les contrôles visuels ou Windows Forms dans les deux RAD :
C# Builder : Visual C# :
![]()
Cette distinction entre visuel et non visuel n'est pas très précise et dépend de la présentation dans le RAD. Cette variabilité de la dénomination n'a aucune importance pour l'utilisateur car tous les composants ont un fonctionnement du code identique.
En effet si nous prenons la classe System.Windows.Forms.MainMenu :
System.ComponentModel.Component
System.Windows.Forms.Menu
System.Windows.Forms.MainMenu
Nous voyons que Visual C# range System.Windows.Forms.MainMenu dans les contrôles alors que C# Builder le range dans les composants (donc non visuels). Ci-dessous les outils de composants proposés par les deux RAD ::
C# Builder Visual C# :
![]()
![]()
Pour pouvoir construire une IHM, il nous faut pouvoir utiliser à minima les composants visuels habituels que nous retrouvons dans les logiciels windows-like. Ici aussi la documentation technique fournie avec le RAD détaillera les différentes entités mises à disposition de l'utilisateur.
1.2 les contrôles sur un formulaire
Voici un exemple de fiche comportant 7 catégories de contrôles différents :
![]()
Il existe des contrôles qui sont des conteneurs visuels, les quatre classes ci-après sont les principales classe de conteneurs visuels de C# :
System.Windows.Forms.Form
System.Windows.Forms.Panel
System.Windows.Forms.GroupBox
System.Windows.Forms.TabPage
Un conteneur visuel permet à d'autres contrôles de s'afficher sur lui et lui communique par lien de parenté des valeurs de propriétés par défaut (police de caractères, couleur du fond,...). Un objet de chacune de ces classes de conteneurs visuels peut être le "parent" de n'importe quel contrôle grâce à sa propriété Parent qui est en lecture et écriture :
public Control Parent {get; set;}
C'est un objet de classe Control qui représente le conteneur visuel du contrôle.
Sur la fiche précédente nous relevons outre le formulaire lui-même, quatre conteneurs visuels répartis en trois catégories de conteneurs visuels :
![]()
Sur chaque conteneur visuel a été déposé un contrôle de classe System.Windows.Forms.Button qui a "hérité" par défaut des caractéristiques de police et de couleur de fond de son parent. Ci-dessous les classes de tous les contrôles déposés :
![]()
Le code C# engendré pour cette interface :
public class WinForm : System .Windows.Forms.Form
{
/// <summary>
/// Variable requise par le concepteur.
/// </summary>
private System .ComponentModel.Container components = null;
private System .Windows.Forms.Panel panel1 ;
private System .Windows.Forms.Label label1 ;
private System .Windows.Forms.Label label2 ;
private System .Windows.Forms.Panel panel2 ;
private System .Windows.Forms.PictureBox pictureBox1 ;
private System .Windows.Forms.Button button1 ;
private System .Windows.Forms.TextBox textBox1 ;
private System .Windows.Forms.Button button2 ;
private System .Windows.Forms.GroupBox groupBox1 ;
private System .Windows.Forms.TabControl tabControl1 ;
private System .Windows.Forms.TabPage tabPage1 ;
private System .Windows.Forms.TabPage tabPage2 ;
private System .Windows.Forms.Button button3 ;
private System .Windows.Forms.TextBox textBox2 ;
private System .Windows.Forms.ListBox listBox1 ;
private System .Windows.Forms.Button button4 ;
private System .Windows.Forms.Button button5 ;
private System .Windows.Forms.TextBox textBox3 ;
private System .Windows.Forms.MainMenu mainMenu1 ;
public WinForm ( ) {
//
// Requis pour la gestion du concepteur Windows Form
//
InitializeComponent ( );
//
// TODO: Ajouter tout le code du constructeur après l'appel de InitializeComponent
//
}
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose ( bool disposing ) {
if ( disposing ) {
if ( components != null) {
components.Dispose ( );
}
}
base .Dispose ( disposing );
}
#region Code généré par le concepteur Windows Form
private void InitializeComponent ( )
{
System .Resources.ResourceManager resources =
new System .Resources.ResourceManager ( typeof ( WinForm ));
this.panel1 = new System .Windows.Forms.Panel ( );
this.button2 = new System .Windows.Forms.Button ( );
this.textBox1 = new System .Windows.Forms.TextBox ( );
this.label2 = new System .Windows.Forms.Label ( );
this.label1 = new System .Windows.Forms.Label ( );
this.panel2 = new System .Windows.Forms.Panel ( );
this.button1 = new System .Windows.Forms.Button ( );
this.pictureBox1 = new System .Windows.Forms.PictureBox ( );
this.groupBox1 = new System .Windows.Forms.GroupBox ( );
this.textBox3 = new System .Windows.Forms.TextBox ( );
this.button5 = new System .Windows.Forms.Button ( );
this.tabControl1 = new System .Windows.Forms.TabControl ( );
this.tabPage1 = new System .Windows.Forms.TabPage ( );
this.textBox2 = new System .Windows.Forms.TextBox ( );
this.button3 = new System .Windows.Forms.Button ( );
this.tabPage2 = new System .Windows.Forms.TabPage ( );
this.button4 = new System .Windows.Forms.Button ( );
this.listBox1 = new System .Windows.Forms.ListBox ( );
this.mainMenu1 = new System .Windows.Forms.MainMenu ( );
this.panel1.SuspendLayout ( );
this.panel2.SuspendLayout ( );
this.groupBox1.SuspendLayout ( );
this.tabControl1.SuspendLayout ( );
this.tabPage1.SuspendLayout ( );
this.tabPage2.SuspendLayout ( );
this.SuspendLayout ( );
//
// panel1
//
this.panel1.BackColor = System .Drawing.Color.NavajoWhite ;
this.panel1.Controls.Add (this .button2 );
this.panel1.Controls.Add (this .textBox1 );
this.panel1.Controls.Add (this .label2 );
this.panel1.Location = new System .Drawing.Point ( 32, 40 );
this.panel1.Name = "panel1";
this.panel1.Size = new System .Drawing.Size ( 224, 104 );
this.panel1.TabIndex = 0 ;
//
// button2
//
this.button2.Location = new System .Drawing.Point ( 88, 24 );
this.button2.Name = "button2";
this.button2.Size = new System .Drawing.Size ( 72, 24 );
this.button2.TabIndex = 4 ;
this.button2.Text = "button2";
//
// textBox1
//
this.textBox1.Location = new System .Drawing.Point ( 16, 76 );
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System .Drawing.Size ( 192, 20 );
this.textBox1.TabIndex = 3 ;
this.textBox1.Text = "textBox1";
//
// label2
//
this.label2.BackColor = System .Drawing.SystemColors.Info ;
this.label2.Location = new System .Drawing.Point ( 16, 32 );
this.label2.Name = "label2";
this.label2.Size = new System .Drawing.Size ( 88, 40 );
this.label2.TabIndex = 2 ;
this.label2.Text = "label2";
// toutes ces lignes correspondent à ceci :
![]()
//
// panel2
//
this.panel2.BackColor = System .Drawing.Color.PaleTurquoise ;
this.panel2.Controls.Add (this .button1 );
this.panel2.Controls.Add (this .pictureBox1 );
this.panel2.Location = new System .Drawing.Point ( 200, 16 );
this.panel2.Name = "panel2";
this.panel2.Size = new System .Drawing.Size ( 208, 112 );
this.panel2.TabIndex = 2 ;
//
// button1
//
this.button1.Location = new System .Drawing.Point ( 24, 48 );
this.button1.Name = "button1";
this.button1.Size = new System .Drawing.Size ( 72, 24 );
this.button1.TabIndex = 4 ;
this.button1.Text = "button1";
//
// pictureBox1
//
this.pictureBox1.BackColor = System .Drawing.Color.DarkKhaki ;
this.pictureBox1.Image = (( System .Drawing.Image )( resources.GetObject ("pictureBox1.Image")));
// la ligne précédente charge l'image :
![]()
this.pictureBox1.Location = new System .Drawing.Point ( 120, 32 );
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System .Drawing.Size ( 70, 63 );
this.pictureBox1.SizeMode = System .Windows.Forms.PictureBoxSizeMode.AutoSize ;
this.pictureBox1.TabIndex = 0 ;
this.pictureBox1.TabStop = false ;
// toutes ces lignes correspondent à ceci :
![]()
//
// groupBox1
//
this.groupBox1.BackColor = System .Drawing.Color.SkyBlue ;
this.groupBox1.Controls.Add (this .textBox3 );
this.groupBox1.Controls.Add (this .button5 );
this.groupBox1.Location = new System .Drawing.Point ( 8, 160 );
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System .Drawing.Size ( 184, 104 );
this.groupBox1.TabIndex = 4 ;
this.groupBox1.TabStop = false ;
this.groupBox1.Text = "groupBox1";
//
// textBox3
//
this.textBox3.Location = new System .Drawing.Point ( 8, 72 );
this.textBox3.Name = "textBox3";
this.textBox3.Size = new System .Drawing.Size ( 136, 20 );
this.textBox3.TabIndex = 1 ;
this.textBox3.Text = "textBox3";
//
// button5
//
this.button5.Location = new System .Drawing.Point ( 16, 32 );
this.button5.Name = "button5";
this.button5.Size = new System .Drawing.Size ( 72, 24 );
this.button5.TabIndex = 0 ;
this.button5.Text = "button5";
// toutes ces lignes correspondent à ceci :
![]()
//
// tabControl1
//
this.tabControl1.Controls.Add (this .tabPage1 );
this.tabControl1.Controls.Add (this .tabPage2 );
this.tabControl1.Location = new System .Drawing.Point ( 224, 144 );
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0 ;
this.tabControl1.Size = new System .Drawing.Size ( 200, 120 );
this.tabControl1.TabIndex = 5 ;
//
// tabPage1
//
this.tabPage1.BackColor = System .Drawing.Color.DarkTurquoise ;
this.tabPage1.Controls.Add (this .textBox2 );
this.tabPage1.Controls.Add (this .button3 );
this.tabPage1.Location = new System .Drawing.Point ( 4, 22 );
this.tabPage1.Name = "tabPage1";
this.tabPage1.Size = new System .Drawing.Size ( 192, 94 );
this.tabPage1.TabIndex = 0 ;
this.tabPage1.Text = "tabPage1";
//
// textBox2
//
this.textBox2.Location = new System .Drawing.Point ( 16, 16 );
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System .Drawing.Size ( 160, 20 );
this.textBox2.TabIndex = 1 ;
this.textBox2.Text = "textBox2";
//
// button3
//
this.button3.Location = new System .Drawing.Point ( 32, 56 );
this.button3.Name = "button3";
this.button3.Size = new System .Drawing.Size ( 128, 24 );
this.button3.TabIndex = 0 ;
this.button3.Text = "button3";
// toutes ces lignes correspondent à ceci :
![]()
//
// tabPage2
//
this.tabPage2.BackColor = System .Drawing.Color.Turquoise ;
this.tabPage2.Controls.Add (this .button4 );
this.tabPage2.Controls.Add (this .listBox1 );
this.tabPage2.Location = new System .Drawing.Point ( 4, 22 );
this.tabPage2.Name = "tabPage2";
this.tabPage2.Size = new System .Drawing.Size ( 192, 94 );
this.tabPage2.TabIndex = 1 ;
this.tabPage2.Text = "tabPage2";
//
// button4
//
this.button4.Location = new System .Drawing.Point ( 8, 32 );
this.button4.Name = "button4";
this.button4.Size = new System .Drawing.Size ( 64, 24 );
this.button4.TabIndex = 1 ;
this.button4.Text = "button4";
//
// listBox1
//
this.listBox1.Location = new System .Drawing.Point ( 80, 8 );
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System .Drawing.Size ( 96, 69 );
this.listBox1.TabIndex = 0 ;
// toutes ces lignes correspondent à ceci :
![]()
//
// label1
//
this.label1.BackColor = System .Drawing.Color.MediumAquamarine ;
this.label1.Location = new System .Drawing.Point ( 48, 8 );
this.label1.Name = "label1";
this.label1.Size = new System .Drawing.Size ( 88, 16 );
this.label1.TabIndex = 1 ;
this.label1.Text = "label1";
// les 6 lignes précédentes correspondent à ceci :
![]()
//
// WinForm
//
this.AutoScaleBaseSize = new System .Drawing.Size ( 5, 13 );
this.ClientSize = new System .Drawing.Size ( 432, 269 );
this.Controls.Add (this .tabControl1 );
this.Controls.Add (this .groupBox1 );
this.Controls.Add (this .panel2 );
this.Controls.Add (this .label1 );
this.Controls.Add (this .panel1 );
this.Menu = this .mainMenu1 ;
this.Name = "WinForm";
this.Text = "WinForm";
this.panel1.ResumeLayout ( false );
this.panel2.ResumeLayout ( false );
this.groupBox1.ResumeLayout ( false );
this.tabControl1.ResumeLayout ( false );
this.tabPage1.ResumeLayout ( false );
this.tabPage2.ResumeLayout ( false );
this.ResumeLayout ( false );
// toutes ces lignes correspondent à ceci :
![]()
}
#endregion
1.3 Influence de la propriété parent sur l'affichage visuel d'un contrôle
Dans l'IHM précédente, programmons par exemple la modification de la propriété Parent du contrôle textBox1 en réaction au click de souris sur les Button button1 et button2.
Il faut abonner le gestionnaire du click de button1 "private void button1_Click" , au délégué button1.Click :
this.button1.Click += new System.EventHandler(this.button1_Click);
De même il faut abonner le gestionnaire du click de button2 "private void button2_Click" , au délégué button2.Click :
this.button2.Click += new System.EventHandler(this.button2_Click);
Le RAD engendre automatiquement les gestionnaires:
private void button1_Click ( object sender, System .EventArgs e ){ }
private void button1_Click ( object sender, System .EventArgs e ){ }
Les lignes d'abonnement sont engendrées dans la méthode InitializeComponent ( ) :
private void InitializeComponent ( )
{ ....
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button2.Click += new System.EventHandler(this.button2_Click);
}
Le code et les affichages obtenus (le textBox1 est positionné par construction en X=16 et Y=76 sur son parent) :
// Gestionnaire du click sur button1 :
private void button1_Click ( object sender, System .EventArgs e ){
textBox1.Parent = panel1 ;
}
Lorsque l'on clique sur le button1, texteBox1 a pour parent panel1 :
![]()
// Gestionnaire du click sur button2 :
private void button2_Click ( object sender, System .EventArgs e ) {
textBox1.Parent = this;
}
Lorsque l'on clique sur le button2, texteBox1 a pour parent la fiche elle-même :
![]()
Le contrôle pictureBox1 permet d'afficher des images : ico, bmp, gif, png, jpg, jpeg
// chargement d'un fichier image dans le pictureBox1 par un click sur button3 :
private void InitializeComponent ( )
{ ....
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button2.Click += new System.EventHandler(this.button2_Click);
this.button3.Click += new System.EventHandler(this.button3_Click);
}
private void button3_Click ( object sender, System .EventArgs e ) {
pictureBox1.Image = Image.FromFile("csharp.jpg") ;
}
Lorsque l'on clique sur le button3, l'image "csharp.jpg" est chargée dans pictureBox1 :
----->
![]()
1.4 Des graphiques dans les formulaires avec le GDI+
Nous avons remarqué que C# possède un contrôle permettant l'affichage d'images de différents formats, qu'en est-il de l'affichage de graphiques construits pendant l'exécution ? Le GDI+ répond à cette question.
Le Graphical Device Interface+ est la partie de NetFrameWork qui fournit les graphismes vectoriels à deux dimensions, les images et la typographie. GDI+ est une interface de périphérique graphique qui permet aux programmeurs d'écrire des applications indépendantes des périphériques physiques (écran, imprimante,...).
Lorsque l'on dessine avec GDI+, on utilise des méthodes de classes situées dans le GDI+, donnant des directives de dessin, ce sont ces méthodes qui, via le CLR du NetFrameWork, font appel aux pilotes du périphérique physique, les programmes ainsi conçus ne dépendent alors pas du matériel sur lequel ils s'afficheront.
Pour dessiner des graphiques sur n'importe quel périphérique d'affichage, il faut un objet Graphics. Un objet de classe System.Drawing.Graphics est associé à une surface de dessin, généralement la zone cliente d'un formulaire (objet de classe Form). Il n'y a pas de constructeur dans la classe Graphics :
![]()
Comme le dessin doit avoir lieu sur la surface visuelle d'un objet visuel donc un contrôle, c'est cet objet visuel qui fournit le fond, le GDI+ fournit dans la classe System.Windows.Forms.Control la méthode CreateGraphics qui permet de créer un objet de type Graphics qui représente le "fond de dessin" du contrôle :
![]()
Syntaxe :
public Graphics CreateGraphics( );
Afin de comprendre comment utiliser un objet Graphics construisons un exemple fictif de code dans lequel on suppose avoir instancié ObjVisuel un contrôle (par exemple : une fiche, un panel,...), on utilise deux méthodes dessin de la classe Graphics pour dessiner un trait et un rectangle :
![]()
Code C#
Explication
Graphics fond = ObjVisuel.CreateGraphics ( );
Obtention d'un fond de dessin sur ObjVisuel (création d'un objet Graphics associé à ObjVisuel)
Pen blackPen = new Pen ( Color.Black, 2 );
Création d'un objet de pinceau de couleur noire et d'épaisseur 2 pixels
fond.DrawLine ( blackPen, 10f, 10f, 50f, 50f );
Utilisation du pinceau blackPen pour tracer une ligne droite sur le fond d'ObjVisuel entre les deux points A(10,10) et B(50,50).
fond.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
Utilisation d'une couleur de brosse SeaGreen, pour remplr l'intérieur d'un rectangle spécifié par une paire de coordonnées (5,70), une largeur(100 pixels) et une hauteur (50 pixels).
Ces quatre instructions ont permis de dessiner le trait noir et le rectangle vert sur le fond du contrôle ObjVisuel représenté ci-dessous par un rectangle à fond blanc :
![]()
Note technique de Microsoft
L'objet Graphics retourné doit être supprimé par l'intermédiaire d'un appel à sa méthode Dispose lorsqu'il n'est plus nécessaire.
La classe Graphics implémente l'interface IDisposable :
public sealed class Graphics : MarshalByRefObject, IDisposable
Les objets Graphics peuvent donc être libérés par la méthode Dispose( ).
Afin de respecter ce conseil d'optimisation de gestion de la mémoire, nous rajoutons dans notre code l'appel à la méthode Dispose de l'objet Graphics. Nous prenons comme ObjVisuel un contrôle de type panel que nous nommons panelDessin ( private System.Windows.Forms.Panel panelDessin ):
//...
Graphics fond = panelDessin.CreateGraphics ( );
Pen blackPen = new Pen ( Color.Black, 2 );
fond.DrawLine ( blackPen, 10f, 10f, 50f, 50f );
fond.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
fond.Dispose( );
//...suite du code où l'objet fond n'est plus utilisé
Nous pouvons aussi utiliser l'instruction using déjà vue (cf. Fenêtres et ressources ch3.3) qui libère automatiquement l'objet par appel à sa méthode Dispose :
//...
using( Graphics fond = panelDessin.CreateGraphics ( ) ) {
Pen blackPen = new Pen ( Color.Black, 2 );
fond.DrawLine ( blackPen, 10f, 10f, 50f, 50f );
fond.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
}
//...suite du code où l'objet fond n'est plus utilisé
1.5 Le dessin doit être persistant
Reprenons le dessin précédent et affichons-le à la demande.
Nous supposons disposer d'un formulaire nommé WinForm1 contenant un panneau nommé panelDessin :
( private System.Windows.Forms.Panel panelDessin )
et un bouton nommé buttonDessin :
( private System.Windows.Forms.Button buttonDessin )
![]()
Nous programmons un gestionnaire de l'événement click du buttonDessin, dans lequel nous copions le code de traçage de notre dessin :
private void buttonDessin_Click(object sender, System.EventArgs e) {
Graphics fond = panelDessin.CreateGraphics ( );
Pen blackPen = new Pen ( Color.Black, 2 );
fond.DrawLine ( blackPen, 10f, 10f, 50f, 50f );
fond.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
fond.Dispose( );
}
Lorsque nous cliquons sur le bouton buttonDessin, le trait noir et le rectangle vert se dessinent sur le fond du panelDessin :
![]()
Faisons apparaître une fenêtre de bloc-note contenant du texte, qui masque partiellement notre formulaire WinForm1 qui passe au second plan comme ci-dessous :
![]()
Si nous nous refocalisons sur le formulaire en cliquant sur lui par exemple, celui-ci repasse au premier plan, nous constatons que notre dessin est abîmé. Le rectangle vert est amputé de la partie qui était recouverte par la fenêtre de bloc-note. Le formulaire s'est bien redessiné, mais pas nos traçés ;
![]()
Il faut cliquer une nouvelle fois sur le bouton pour lancer le redessinement des tracés :
![]()
Il existe un moyen simple permettant d'effectuer le redessinement de nos traçés lorsque le formulaire se redessine lui-même automatiquement : il nous faut "consommer" l'événement Paint du formulaire qui se produit lorsque le formulaire est redessiné (ceci est d'ailleurs valable pour n'importe quel contrôle). La consommation de l'événement Paint s'effectue grâce au gestionnaire Paint de notre formulaire WinForm1 :
private void WinForm1_Paint (object sender, System.Windows.Forms.PaintEventArgs e) {
Graphics fond = panelDessin.CreateGraphics ( );
Pen blackPen = new Pen ( Color.Black, 2 );
fond.DrawLine ( blackPen, 10f, 10f, 50f, 50f );
fond.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
fond.Dispose( );
}
Le RAD a enregistré (abonné) le gestionnaire WinForm1_Paint auprès du délégué Paint dans le corps de laméthode InitializeComponent :
private void InitializeComponent( ) {
...
this.Paint += new System.Windows.Forms.PaintEventHandler ( this.WinForm1_Paint );
...
}
1.6 Deux exemples de graphiques sur plusieurs contrôles
Premier exemple : une méthode générale pour tout redessiner.
Il est possible de dessiner sur tous les types de conteneurs visuels ci-dessous un formulaire nommé WinForm et deux panel (panel2 : jaune foncé et panel1 : violet), la label1 ne sert qu'à afficher du texte en sortie :
![]()
Nous écrivons une méthode TracerDessin permettant de dessiner sur le fond de la fiche, sur le fond des deux panel et d'écrire du texte sur le fond d'un panel. La méthode TracerDessin est appelée dans le gestionnaire de l'événement Paint du formulaire lors de son redessinement de la fiche afin d'assurer la persistance de tous les traçés. Voici le code que nous créons :
private void InitializeComponent( ) {
...
this.Paint += new System.Windows.Forms.PaintEventHandler ( this.WinForm_Paint );
...
}
private void WinForm_Paint (object sender, System.Windows.Forms.PaintEventArgs e) {
TracerDessin ( e.Graphics ) ;
/* Explications sur l'appel de la méthode TracerDessin :
Le paramètre e de type PaintEventArgs contient les données relatives à l'événement Paint
en particulier une propriété Graphics qui renvoie le graphique utilisé pour peindre sur la fiche
c'est pourquoi e.Graphics est passé comme fond en paramètre à notre méthode de dessin.
*/
}
private void TracerDessin ( Graphics x ){
string Hdcontext ;
Hdcontext = x.GetType ( ) .ToString ( );
label1.Text = "Graphics x : " + Hdcontext.ToString ( );
x.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
using( Graphics g = this .CreateGraphics ( ) ) {
g.FillRectangle ( Brushes.SkyBlue,5,10,100,50 );
}
using( Graphics g = panel1.CreateGraphics ( ) ) {
g.FillEllipse ( Brushes.MediumSlateBlue,5,10,40,30 );
}
using( Graphics h = panel2.CreateGraphics ( ) ) {
h.FillEllipse ( Brushes.Tomato,10,15,120,80 );
h.DrawString ("Bonjour" , new Font (this .Font.FontFamily.Name,18 ) ,Brushes.Lime,15,25 );
}
}
L'exécution de code produit l'affichage suivant :
![]()
Illustrons les actions de dessin de chaque ligne
de code de la méthode TracerDessin :
private void TracerDessin ( Graphics x ) {
![]()
On dessine deux rectangles sur le fond de la fiche, nous notons que ces deux rectangles ont une intersection non vide avec le panel2 (jaune foncé)et que cela n'altère pas le dessin du panel. En effet le panel est un contrôle et donc se redessine lui-même. Nous en déduisons que le fond graphique est situé "en dessous" du dessin des contrôles.
![]()
L'instruction dessine l'ellipse bleue sur le fond du panel1
![]()
La première instruction dessine l'ellipse rouge, la seconde écrit le texte "Bonjour" en vert sur le fond du panel2.
Deuxième exemple : traçé des dessins sur des événements spécifiques
Le deuxième exemple montre que l'on peut dessiner aussi sur le fond d'autres contrôles différents des contrôles conteneurs; nous dessinons deux rectangles vert et bleu sur le fond du formulaire et un petit rectangle bleu ciel dans un ListBox, un TextBox et Button déposés sur le formulaire :
![]()
Les graphiques sont gérés dans le code ci-après :
namespace ProjWindowsApplication2
{
/// <summary>
/// Description Résumé de WinForm1.
/// </summary>
public class WinForm1 : System.Windows.Forms.Form
{
/// <summary>
/// Variable requise par le concepteur.
/// </summary>
private System.ComponentModel.Container components = null ;
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private WinForm1( )
{
//
// Requis pour la gestion du concepteur Windows Form
//
InitializeComponent();
//
// TODO: Ajouter tout le code du constructeur après l'appel de InitializeComponent
//
}
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose (bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Code généré par le concepteur Windows Form
/// <summary>
/// Méthode requise pour la gestion du concepteur - ne pas modifier
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent( )
{
this.listBox1 = new System.Windows.Forms.ListBox( );
this.textBox1 = new System.Windows.Forms.TextBox( );
this.button1 = new System.Windows.Forms.Button( );
this.SuspendLayout( );
//
// listBox1
//
this.listBox1.Items.AddRange ( new object[] {
"zéro",
"un",
"deux",
"trois",
"quatre",
"cinq",
"FIN" } );
this.listBox1.Location = new System.Drawing.Point(224, 8);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(144, 95);
this.listBox1.TabIndex = 9;
this.listBox1.SelectedIndexChanged += new System.EventHandler ( this.listBox1_SelectedIndexChanged );
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(8, 72);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(200, 20);
this.textBox1.TabIndex = 8;
this.textBox1.Text = "textBox1";
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// button1
//
this.button1.Location = new System.Drawing.Point(24, 24);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(144, 32);
this.button1.TabIndex = 7;
this.button1.Text = "button1";
this.button1.Paint += new System.Windows.Forms.PaintEventHandler(this.button1_Paint);
//
// WinForm1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(384, 117);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "WinForm1";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "WinForm1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.WinForm1_Paint);
this.ResumeLayout(false);
}
#endregion
//-- dessin persistant sur le fond de la fiche par gestionnaire Paint:
private void WinForm1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle ( Brushes.SeaGreen,5,70,100,50 );
g.FillRectangle ( Brushes.SkyBlue,5,10,100,50 );
}
//-- dessin persistant sur le fond du bouton par gestionnaire Paint:
private void button1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics x = e.Graphics;
x.FillRectangle ( Brushes.SkyBlue,5,5,20,20 );
}
//-- dessin non persistant sur le fond du ListBox par gestionnaire SelectedIndexChange :
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
Rectangle Rect = listBox1.GetItemRectangle(listBox1.SelectedIndex);
int Haut = listBox1.ItemHeight;
textBox1.Text= "x="+Rect.X.ToString()+" y="+Rect.Y.ToString()+" h="+Haut.ToString();
using ( Graphics k = listBox1.CreateGraphics( ) )
{
k.FillRectangle(Brushes.SkyBlue,Rect.X,Rect.Y,Haut,Haut);
}
}
//-- dessin non persistant sur le fond du TextBox par gestionnaire TextChanged :
private void textBox1_TextChanged(object sender, System.EventArgs e)
{
using (Graphics k = textBox1.CreateGraphics( ) )
{
k.FillRectangle(Brushes.SkyBlue,5,5,10,10);
}
}
}
}
Après exécution, sélection de la 3ème ligne de la liste et ajout d'un texte au clavier dans le TextBox :
![]()