IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Problème avec l'évènement « OnPaint »


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 106
    Par défaut Problème avec l'évènement « OnPaint »
    Bonjour,

    J'utilise l'évènement « OnPaint » de ma Forme pour y dessiner une image de fond.
    Je ne peux pas utiliser la propriété .BackgroundImage car je la dessine autrement.
    Cependant, j'ai quelques souçis lorsque survient l'évènement « OnPaint » :

    Tout d'abord, l'évènement est envoyé quand je passe ma souris sur ma forme.
    À ce moment là, l'image se redessine inutilement et j'aimerais pouvoir éviter cela.

    Ensuite, le programme ralentit lors de la création de l'image sur la Forme, surtout lorsque l'on change la grandeur de la fenêtre.

    J'ai ajouté ceci dans le Public Sub New(), mais je ne vois pas trop de différence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            SetStyle(ControlStyles.DoubleBuffer, True)
    Comment peut-on empêcher ce ralentissement (ou le réduire)?

    Merci d'avance,
    Éric

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 198
    Par défaut
    réduire le nombre d'évènement levés c'est impossible, c'est gdi+ qui est fait comme ça ... et ca peut monter à plusieurs dizaines par seconde je crois
    par contre sur vista/7, windows met les forms en cache sur une surface directX je crois et donc il n'y a plus d'évènements de déplacement, et moins aussi sur le reste

    pour gagner du temps, tu peux utiliser un buffer manuel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    private _Buffer as system.drawing.bufferedgraphics
     
    overrides sub onsizechanged
      if _Buffer isnot nothing then _Buffer.Dispose ' vu qu'on risque de passer plusieurs fois ici, on s'arrange pour ne pas faire de fuite de mémoire en détruisant l'ancienne valeur
      _buffer = system.drawing.bufferedgraphicsManager.Current.Allocate(me.creategraphics,me.clientrectangle)
    end sub ' on demande l'allocation du buffer en lui donnant me.creategraphics comme surface de rendu par défaut, et la faille
     
     
    overrides sub onpaint
      _buffer.render(e.graphics) ' on demande le rendu sur le graphics fournit par onpaint
    ens sub
    après tout ce que tu faisais sur e.graphics dans onpaint tu le fais sur _buffer.graphics, et donc où tu veux dans le code (plus un _buffer.render dans la foulée car le buffer n'est pas visible)
    l'instruction render est instantannée

    code fait de tête, il y a peut etre quelques adaptations à faire



    Citation Envoyé par Eric_M Voir le message
    Je ne peux pas utiliser la propriété .BackgroundImage car je la dessine autrement.
    mon histoire de buffer c'est utile quand on change le dessin plusieurs fois
    si c'est juste pour une image, tu peux la dessiner sur un drawing.bitmap à ta facon et mettre ce bitmap dans BackgroundImage
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 106
    Par défaut
    Merci Pol63 pour ta réponse.

    J'ai mis un Buffer comme tu me l'as conseillé, mais je ne croix pas que c'est utile pour ce que je fais.

    Bon, pour être plus clair sur ce que je fait exactement,
    je dessine une image, mais je l'aligne à droite de ma forme.
    C'est pour cela que je n'utilise pas la proriété BackgroundImage car elle me permet que de l'aligner à gauche (center, zoom, etc.) et non à droite.

    Ensuite, je crée une image qui est ma couleur de fond et je l'a peint avant l'image.
    Je ne peux pas simplement changer la couleur avec Me.Backcolor car le tout est peint sur de la transparence (Windows 7)

    Pour finir, Je dessine des bordures.

    TOUT cela est fait que dessus et sur ma barre de navigation, qui contient la plupart des contrôles de ma forme.

    Voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
        Public FondDÉcran As Image
        Public CouleurDeFond As Color
     
        Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaintBackground(e)
     
            'Modes de dessin
            e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
            e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
     
            'Représente les mesures de la barre où tous mes controles sont dessus
            Dim PnlTop = PnlNavigationStrip.Top
            Dim PnlHeight = PnlNavigationStrip.Height
     
            e.Graphics.Clip = New Region(e.ClipRectangle)
     
            'Exclue le reste (en Dessous de ma barre de navigation)
            e.Graphics.ExcludeClip(New Rectangle(0, PnlTop + PnlHeight, Me.Width, Me.Height))
     
            'Peint la couleur de fond
            REM Je ne peux pas simplement changer la couleur avec Me.Backcolor car le tout est peint sur de la transparence (Windows 7)
            Dim b As New Bitmap(1, 1)
            Dim g As Graphics = Graphics.FromImage(b)
            g.Clear(CouleurDeFond)
            e.Graphics.DrawImage(b, 0, 0, Me.ClientSize.Width + 10, PnlTop + PnlHeight)
     
            'Dessine l'image de fond
            e.Graphics.DrawImage(FondDÉcran, Me.Width - FondDÉcran.Width - SystemInformation.SizingBorderWidth - 2, _
                                                                      0, _
                                                                   FondDÉcran.Width, _
                                                                   FondDÉcran.Height)
            'Dessine des bordures
            Dim p As New Pen(Color.FromArgb(150, 255, 255, 255))
            'Haut
            e.Graphics.DrawLine(Pens.Black, 1, 1, Me.Width, 1)
            e.Graphics.DrawLine(p, 1, 2, Me.Width, 2)
            'Gauche
            e.Graphics.DrawLine(Pens.Black, 1, 1, 1, PnlTop + PnlHeight)
            e.Graphics.DrawLine(p, 2, 2, 2, PnlTop + PnlHeight)
            'Droite
            e.Graphics.DrawLine(Pens.Black, Me.Width, 1, Me.Width, PnlTop + PnlHeight)
            e.Graphics.DrawLine(p, Me.Width - 1, 2, Me.Width - 1, PnlTop + PnlHeight)
        End Sub
    Et avec un Buffer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
        Public FondDÉcran As Image
        Public CouleurDeFond As Color
     
        Private _Buffer As System.Drawing.BufferedGraphics
     
        Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
            MyBase.OnSizeChanged(e)
            On Error Resume Next
            If _Buffer IsNot Nothing Then _Buffer.Dispose() ' vu qu'on risque de passer plusieurs fois ici, on s'arrange pour ne pas faire de fuite de mémoire en détruisant l'ancienne valeur
            _buffer = system.drawing.bufferedgraphicsManager.Current.Allocate(Me.creategraphics, Me.clientrectangle)
        End Sub ' on demande l'allocation du buffer en lui donnant me.creategraphics comme surface de rendu par défaut, et la faille
     
     
        Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaintBackground(e)
            _Buffer.Render(e.Graphics) ' on demande le rendu sur le graphics fournit par onpaint
     
            'Modes de dessin
            _Buffer.Graphics.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
            _Buffer.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
     
            'Représente les mesures de la barre où tous mes controles sont dessus
            Dim PnlTop = PnlNavigationStrip.Top
            Dim PnlHeight = PnlNavigationStrip.Height
     
            _Buffer.Graphics.Clip = New Region(e.ClipRectangle)
     
            'Exclue le reste (en Dessous de ma barre de navigation)
            _Buffer.Graphics.ExcludeClip(New Rectangle(0, PnlTop + PnlHeight, Me.Width, Me.Height))
     
            'Peint la couleur de fond
            REM Je ne peux pas simplement changer la couleur avec Me.Backcolor car le tout est peint sur de la transparence (Windows 7)
            Dim b As New Bitmap(1, 1)
            Dim g As Graphics = Graphics.FromImage(b)
            g.Clear(CouleurDeFond)
            _Buffer.Graphics.DrawImage(b, 0, 0, Me.ClientSize.Width + 10, PnlTop + PnlHeight)
     
            'Dessine l'image de fond
            _Buffer.Graphics.DrawImage(FondDÉcran, Me.Width - FondDÉcran.Width - SystemInformation.SizingBorderWidth - 2, _
                                                                       0, _
                                                                    FondDÉcran.Width, _
                                                                    FondDÉcran.Height)
            'Dessine des bordures
            Dim p As New Pen(Color.FromArgb(150, 255, 255, 255))
            'Haut
            _Buffer.Graphics.DrawLine(Pens.Black, 1, 1, Me.Width, 1)
            _Buffer.Graphics.DrawLine(p, 1, 2, Me.Width, 2)
            'Gauche
            _Buffer.Graphics.DrawLine(Pens.Black, 1, 1, 1, PnlTop + PnlHeight)
            _Buffer.Graphics.DrawLine(p, 2, 2, 2, PnlTop + PnlHeight)
            'Droite
            _Buffer.Graphics.DrawLine(Pens.Black, Me.Width, 1, Me.Width, PnlTop + PnlHeight)
            _Buffer.Graphics.DrawLine(p, Me.Width - 1, 2, Me.Width - 1, PnlTop + PnlHeight)
        End Sub
    Merci encore.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 198
    Par défaut
    On Error Resume Next
    Aïe ca pique les yeux ^^

    sinon wpf c'est pas mal ... ca permet de tout faire en natif et de ne rien bricoler
    et puis ca gère la transparence réellement, alors qu'en winform c'est un bricolage
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 106
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    On Error Resume Next
    Aïe ca pique les yeux ^^
    Si je ne mettais pas ça, je recevais une erreur lors de l'ouverture de la Forme.

    En tous cas, je croix que je vais rester en win32 car sa serait long de convertir mon logiciel en wpf..

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 198
    Par défaut
    Citation Envoyé par Eric_M Voir le message
    Si je ne mettais pas ça, je recevais une erreur lors de l'ouverture de la Form.

    lol ...

    déjà quand on a une erreur on chercher pourquoi et on corrige le bug
    de plus quand vraiment on veut gérer des erreurs imprévues, on utilise surtout pas on error resume next !
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. Problème avec les évènement de mes controle
    Par napegadie dans le forum VB.NET
    Réponses: 5
    Dernier message: 17/08/2007, 12h41
  2. [JComboBox] Problème avec un événement
    Par cysboy dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 21/03/2007, 15h34
  3. [C# 2.0] Problème avec l'évènement de mon userControl
    Par manu94600 dans le forum ASP.NET
    Réponses: 2
    Dernier message: 04/11/2006, 20h36
  4. problème avec l'événement onBlur
    Par danyboy85 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 26/04/2006, 11h48
  5. [wxpython] problème avec les événements souris
    Par kalimero dans le forum wxPython
    Réponses: 2
    Dernier message: 13/11/2005, 15h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo