Rendu d'un contrôle Windows Forms

Le rendu fait référence au processus de création d’une représentation visuelle sur l’écran d’un utilisateur. Windows Forms utilise GDI (la nouvelle bibliothèque graphique Windows) pour le rendu. Les classes managées qui fournissent l’accès à GDI se trouvent dans l’espace System.Drawing de noms et ses sous-espaces.

Les éléments suivants sont impliqués dans le rendu du contrôle :

  • Fonctionnalité de dessin fournie par la classe System.Windows.Forms.Controlde base .

  • Éléments essentiels de la bibliothèque graphique GDI.

  • Géométrie de la zone de dessin.

  • Procédure de libération des ressources graphiques.

Fonctionnalité de dessin fournie par le contrôle

La classe Control de base fournit des fonctionnalités de dessin par le biais de son Paint événement. Un contrôle déclenche l’événement Paint chaque fois qu’il doit mettre à jour son affichage. Pour plus d’informations sur les événements dans .NET Framework, consultez Gestion et déclenchement d’événements.

La classe de données d’événement pour l’événement Paint , PaintEventArgscontient les données nécessaires pour dessiner un contrôle , un handle vers un objet graphique et un objet rectangle qui représente la région à dessiner. Ces objets sont affichés en gras dans le fragment de code suivant.

Public Class PaintEventArgs  
   Inherits EventArgs  
   Implements IDisposable  
  
   Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle  
      ...  
   End Property  
  
   Public ReadOnly Property Graphics() As System.Drawing.Graphics  
      ...  
   End Property  
   ' Other properties and methods.  
   ...  
End Class  
public class PaintEventArgs : EventArgs, IDisposable {  
public System.Drawing.Rectangle ClipRectangle {get;}  
public System.Drawing.Graphics Graphics {get;}  
// Other properties and methods.  
...  
}  

Graphics est une classe managée qui encapsule les fonctionnalités de dessin, comme décrit dans la discussion de GDI plus loin dans cette rubrique. Il ClipRectangle s’agit d’une instance de la Rectangle structure et définit la zone disponible dans laquelle un contrôle peut dessiner. Un développeur de contrôles peut calculer l’utilisation ClipRectangle de la ClipRectangle propriété d’un contrôle, comme décrit dans la discussion de géométrie plus loin dans cette rubrique.

Un contrôle doit fournir une logique de rendu en remplaçant la OnPaint méthode qu’il hérite de Control. OnPaint obtient l’accès à un objet graphique et à un rectangle à dessiner à travers les Graphics propriétés de ClipRectangle l’instance PaintEventArgs passée.

Protected Overridable Sub OnPaint(pe As PaintEventArgs)  
protected virtual void OnPaint(PaintEventArgs pe);  

La OnPaint méthode de la classe de base Control n’implémente aucune fonctionnalité de dessin, mais appelle simplement les délégués d’événement inscrits auprès de l’événement Paint . Lorsque vous remplacez OnPaint, vous devez généralement appeler la OnPaint méthode de la classe de base afin que les délégués inscrits reçoivent l’événement Paint . Toutefois, les contrôles qui peintnt toute leur surface ne doivent pas appeler les classes de OnPaintbase, car cela introduit un scintillement. Pour obtenir un exemple de substitution de l’événement OnPaint , consultez la procédure : créer un contrôle Windows Forms qui affiche la progression.

Remarque

N’appelez OnPaint pas directement à partir de votre contrôle ; à la place, appelez la Invalidate méthode (héritée de ) Controlou une autre méthode qui appelle Invalidate. La Invalidate méthode appelle OnPaintà son tour . La Invalidate méthode est surchargée et, selon les arguments fournis à Invalidatee, un contrôle redessine une partie ou l’ensemble de sa zone d’écran.

La classe de base Control définit une autre méthode utile pour le dessin , la OnPaintBackground méthode.

Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)  
protected virtual void OnPaintBackground(PaintEventArgs pevent);  

OnPaintBackground peint l’arrière-plan (et ainsi la forme) de la fenêtre et est garanti être rapide, tandis que OnPaint peint les détails et peut être plus lent, car les demandes de peinture individuelles sont combinées en un Paint événement qui couvre toutes les zones qui doivent être redessinées. Vous souhaiterez peut-être appeler si OnPaintBackground , par exemple, vous souhaitez dessiner un arrière-plan de couleur dégradée pour votre contrôle.

Bien qu’elle OnPaintBackground ait une nomenclature de type événement et accepte le même argument que la OnPaint méthode, OnPaintBackground n’est pas une véritable méthode d’événement. Il n’existe aucun PaintBackground événement et OnPaintBackground n’appelle pas de délégués d’événement. En cas de substitution de la OnPaintBackground méthode, une classe dérivée n’est pas nécessaire pour appeler la OnPaintBackground méthode de sa classe de base.

Principes de base de GDI+

La Graphics classe fournit des méthodes pour dessiner différentes formes telles que des cercles, des triangles, des arcs et des points de suspension, ainsi que des méthodes d’affichage de texte. L’espace System.Drawing de noms et ses sous-espaces de noms contiennent des classes qui encapsulent des éléments graphiques tels que des formes (cercles, rectangles, arcs et autres), des couleurs, des polices, des pinceaux, etc. Pour plus d’informations sur GDI, consultez Utilisation de classes Graphics managées. Les éléments essentiels de GDI sont également décrits dans la procédure : créer un contrôle Windows Forms qui affiche la progression.

Géométrie de la région de dessin

La ClientRectangle propriété d’un contrôle spécifie la région rectangulaire disponible pour le contrôle sur l’écran de l’utilisateur, tandis que la ClipRectangle propriété de PaintEventArgs la zone qui est réellement peinte. (N’oubliez pas que la peinture est effectuée dans la Paint méthode événementielle qui prend une PaintEventArgs instance comme argument). Un contrôle peut avoir besoin de peindre uniquement une partie de sa zone disponible, comme c’est le cas lorsqu’une petite section de l’affichage du contrôle change. Dans ces situations, un développeur de contrôles doit calculer le rectangle réel à dessiner et à passer à Invalidate. Les versions surchargées de Invalidate cette prise Rectangle ou Region en tant qu’argument utilisent cet argument pour générer la ClipRectangle propriété de PaintEventArgs.

Le fragment de code suivant montre comment le FlashTrackBar contrôle personnalisé calcule la zone rectangulaire à dessiner. La client variable indique la ClipRectangle propriété. Pour obtenir un exemple complet, consultez Comment : créer un contrôle Windows Forms qui affiche la progression.

Rectangle invalid = new Rectangle(
    client.X + min,
    client.Y,
    max - min,
    client.Height);

Invalidate(invalid);
Dim invalid As Rectangle = New Rectangle( _
    client.X + lmin, _
    client.Y, _
    lmax - lmin, _
    client.Height)

Invalidate(invalid)

Libération des ressources graphiques

Les objets graphiques sont coûteux, car ils utilisent des ressources système. Ces objets incluent des instances de la System.Drawing.Graphics classe ainsi que des instances de System.Drawing.Brush, System.Drawing.Penet d’autres classes graphiques. Il est important de créer une ressource graphique uniquement quand vous en avez besoin et de la libérer dès que vous avez terminé de l’utiliser. Si vous créez un type qui implémente l’interface IDisposable , appelez sa Dispose méthode lorsque vous avez terminé de l’utiliser pour libérer des ressources.

Le fragment de code suivant montre comment le FlashTrackBar contrôle personnalisé crée et libère une Brush ressource. Pour obtenir le code source complet, consultez Guide pratique pour créer un contrôle Windows Forms qui affiche la progression.

private Brush baseBackground = null;
Private baseBackground As Brush
base.OnPaint(e);
if (baseBackground == null) {
    if (showGradient) {
        baseBackground = new LinearGradientBrush(new Point(0, 0),
                                                 new Point(ClientSize.Width, 0),
                                                 StartColor,
                                                 EndColor);
    }
    else if (BackgroundImage != null) {
        baseBackground = new TextureBrush(BackgroundImage);
    }
    else {
        baseBackground = new SolidBrush(BackColor);
    }
}
MyBase.OnPaint(e)

If (baseBackground Is Nothing) Then

    If (myShowGradient) Then
        baseBackground = New LinearGradientBrush(New Point(0, 0), _
                                                 New Point(ClientSize.Width, 0), _
                                                 StartColor, _
                                                 EndColor)
    ElseIf (BackgroundImage IsNot Nothing) Then
        baseBackground = New TextureBrush(BackgroundImage)
    Else
        baseBackground = New SolidBrush(BackColor)
    End If

End If
protected override void OnResize(EventArgs e) {
    base.OnResize(e);
    if (baseBackground != null) {
        baseBackground.Dispose();
        baseBackground = null;
    }
}
Protected Overrides Sub OnResize(ByVal e As EventArgs)
    MyBase.OnResize(e)
    If (baseBackground IsNot Nothing) Then
        baseBackground.Dispose()
        baseBackground = Nothing
    End If
End Sub

Voir aussi