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 :

Rapidité graphique, DrawImage ou DrawString ?


Sujet :

VB.NET

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut Rapidité graphique, DrawImage ou DrawString ?
    Bonjour, je suis en train de réaliser une application graphique en VB.NET sur PDA (WM5) qui doit tourner rapidement (25hz pour le rafraichissement). Je dois afficher quelques cercles et quelques traits, ainsi que du texte dans une police spécifique.
    Mon problème est que lorsque je me contente d'afficher des traits et des cercles, je respecte largement la fréquence de rafraichissement à 25hz, mais dès que je fait du drawstring, je tombe à 15hz ...
    Ma question est la suivante : si je crée une image pour chaque caractère de la police (principalement des chiffres), serait il plus rapide d'afficher ces images via drawimage plutot que d'utiliser drawstring ? Ou existe t'il une autre solution plus rapide ?
    D'avance merci de votre aide !

  2. #2
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Bonjour.

    Essayes d'abord de passer par un buffer --> tu créés une bitmap, tu créés un graphics à partir de cette image et tu dessines dans le graphics.
    Ensuite, dans le graphics correspondant à ton composant, tu fais un drawimage du bitmap.

    Exemple :
    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
     
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
     
            Dim ibufferImage As Bitmap = New Bitmap(Me.Bounds.Width, Me.Bounds.Height)
            Dim gd As Graphics = Graphics.FromImage(ibufferImage)
            gd.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            gd.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit '.AntiAlias '.ClearTypeGridFit '.AntiAlias
            '
            ' Background du parent
            '
            MyBase.OnPaintBackground(New PaintEventArgs(gd, Me.Bounds))
     
            gd.DrawString(Text, Font, Brushes.White, New Point(0, 0))
     
            e.Graphics.DrawImage(ibufferImage, 0, 0)
     
            gd.Dispose()
     
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
    Aprés en jouant sur la qualité du rendu SmoothingMode et TextRenderingHint, il y moyen de grapiller un peu...

    PS : le code ci-dessus n'est pas optimisé, dans l'idéal il ne faudrait pas reconstituer la bitmap à chaque fois...

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Merci de ta réponse olsimare.
    Comme je travaille avec compact framework, le "SmoothingMode" et le "TextRenderingHint" ne sont pas compris ... Et je n'ai pas d'évènement "onpaint" ...
    Par contre, pour ce qui est de l'optimisation, je ne recrée pas le bitmap à chaque fois.
    Voici un bout de mon code, ce sera plus clair :

    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
     
    Public Class Form1
        Dim objBitMap
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
            objBitMap = New Bitmap(Pic_Temp.Image) 'je crée un bitmap une seule fois au démarrage à partir d'une image contenue dans un picturebox
        End Sub
     
        Private Sub Tmr_General_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tmr_General.Tick
            Dim objGraphics As Graphics
            Dim MaFont As Font
            Dim MaBrush As Brush
            objGraphics = Graphics.FromImage(objBitMap)
            objGraphics.Clear(Color.Black)
            objGraphics.DrawImage(Pic_Temp.Image, 0, 0) 'pic_temp est une picturebox contenant une image utilisée pour le fond
            MaFont = New Font("DS-Digital", 75, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
            objGraphics.DrawString("toto", MaFont, MaBrush, 0, 0)
            Me.Pic_Tdb.Image = objBitMap 'je met objbitmap comme image dans ma picturebox de destination
            objGraphics.Dispose()
            objGraphics = Nothing
        End Sub
    End Class
    C'est très schématisé, j'affiche un tas de données en réalité.
    Peut être je m'y prend mal ?
    Une autre piste pourrait etre Direct Draw (les fonctions DirectX sont prise en compte dans le compact framework), mais ça devient nettement plus complexe.
    Qu'en pensez vous ?

  4. #4
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Re.

    Quand je disais qu'il ne fallait pas recréer le bitmap, je me suis mal exprimé, je sous-entendais de ne pas refaire également le dessin dans la bitmap, c'est à dire de ne redessiner la bitmap qu'en cas de changement de l'une des composantes du dessin.

    Donc dans ce cas, personnellement, je ne passerai pas par une picturebox, c'est inutile. Une class héritée de controls devrait suffire pour du simple affichage.

    Un exemple :
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    Public Class ccExempleProto111
        Inherits Control
     
        Private WithEvents t As New Timer
        Private bBuffer As Bitmap = Nothing
        Private r As Rectangle = Rectangle.Empty
        Private dtStarted As Date = Now
        Public Sub New()
            t.Interval = 1
            If Not System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Designtime Then
                t.Start()
                dtStarted = Now
            End If
        End Sub
        Private ReadOnly Property Buffer() As Bitmap
            Get
                If bBuffer Is Nothing Then
                    ResetBuffer()
                End If
                Return bBuffer
            End Get
        End Property
        Private Sub ResetBuffer()
            If r = Rectangle.Empty Then
                r = New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            End If
            bBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
     
            Dim MaFont As Font
            Dim MaBrush As Brush
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
     
            gd.DrawString(intTickCount.ToString, MaFont, MaBrush, New Point(0, 0))
     
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, New Point(0, 50))
     
            gd.DrawString(Now.ToString, MaFont, MaBrush, New Point(0, 100))
     
            gd.DrawRectangle(Pens.Red, r)
            gd.Dispose()
            Me.Refresh()
        End Sub
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(Me.Buffer, 0, 0)
        End Sub
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
        Private intStep As Integer = 1
        Private intTickCount As Integer = 0
        Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
            r.Width -= intStep
            r.Height -= intStep
            intTickCount += 1
            ResetBuffer()
            If r.Width = 1 Or r.Height = 1 _
            Or r.Width = Me.Bounds.Width Or r.Height = Me.Bounds.Width Then
                intStep = -intStep
            End If
        End Sub
    End Class
    Et tu le mets sur une form.

    Conclusion :
    sur un Dual Core à 1,8GoHz de base à 3% de CPU, ça me fait monter à 12% pour 60 Hertz (à peu prés)... (j'ai m'y un interval à 1ms sachant trés bien que le rafraichissement en une ms, fallait pas réver).
    Donc pas génial pour dessiner un rectangle et 3 textes !

    C'est à essayer, mais il ne faut de toute façon pas s'attendre à des performances terrifiantes avec GDI+...

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Bonsoir, merci pour ta réponse.
    Au risque de paraître un peu ... débutant, tu le places comment ton code dans la form ?
    Lorsque je crée le projet avec une form form1.vb, le code qui se crée c'est ça :
    Public Class Form1
    End Class

    J'ai essayé de le mettre à la suite, mais ça me génère une erreur : Handle de liaison non valide

    Merci de ton aide !

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    erreur de ma part, c'était un problème de service désactivé nécessaire pour le débogage ... oups
    Par contre je ne sais pas ou mettre ton code. Alors j'ai essayé autre chose :
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    Public Class Form1
     
        Private bBuffer As Bitmap = Nothing
        Private r As Rectangle = Rectangle.Empty
        Private dtStarted As Date = Now
        Private intStep As Integer = 1
        Private intTickCount As Integer = 0
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Label1.Text = "toto"
        End Sub
     
        Private ReadOnly Property Buffer() As Bitmap
            Get
                If bBuffer Is Nothing Then
                    ResetBuffer()
                End If
                Return bBuffer
            End Get
        End Property
     
        Private Sub ResetBuffer()
            If r = Rectangle.Empty Then
                r = New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            End If
            bBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
     
            Dim MaFont As Font
            Dim MaBrush As Brush
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
     
            gd.DrawString(intTickCount.ToString, MaFont, MaBrush, New Point(0, 0))
     
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, New Point(0, 50))
     
            gd.DrawString(Now.ToString, MaFont, MaBrush, New Point(0, 100))
     
            gd.DrawRectangle(Pens.Red, r)
            gd.Dispose()
            Me.Refresh()
        End Sub
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(Me.Buffer, 0, 0)
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
     
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            r.Width -= intStep
            r.Height -= intStep
            intTickCount += 1
            ResetBuffer()
            If r.Width = 1 Or r.Height = 1 _
            Or r.Width = Me.Bounds.Width Or r.Height = Me.Bounds.Width Then
                intStep = -intStep
            End If
     
        End Sub
    End Class
    De cette façon ça marche, mais je ne sais pas si ça revient au même que ta façon ... ?

  7. #7
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Bonjour.

    C'est pas tout à fait la même chose car là du joue sur le dessin de la Form. Le code donné permet de créer un control que tu peux directement mettre dans la form via la boîte à outils (aprés avoir regénérer il me semble).

    Par exemple j'avais testé avec une form Form12 :
    Dans le Form12.Designer.vb
    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
     
    <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
    Partial Class Form12
        Inherits System.Windows.Forms.Form
     
        'Form remplace la méthode Dispose pour nettoyer la liste des composants.
        <System.Diagnostics.DebuggerNonUserCode()> _
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            Try
                If disposing AndAlso components IsNot Nothing Then
                    components.Dispose()
                End If
            Finally
                MyBase.Dispose(disposing)
            End Try
        End Sub
     
        'Requise par le Concepteur Windows Form
        Private components As System.ComponentModel.IContainer
     
        'REMARQUE*: la procédure suivante est requise par le Concepteur Windows Form
        'Elle peut être modifiée à l'aide du Concepteur Windows Form.  
        'Ne la modifiez pas à l'aide de l'éditeur de code.
        <System.Diagnostics.DebuggerStepThrough()> _
        Private Sub InitializeComponent()
            Me.CcExempleProto1111 = New WindowsApplication1.ccExempleProto111
            Me.SuspendLayout()
            '
            'CcExempleProto1111
            '
            Me.CcExempleProto1111.Location = New System.Drawing.Point(12, 12)
            Me.CcExempleProto1111.Name = "CcExempleProto1111"
            Me.CcExempleProto1111.Size = New System.Drawing.Size(231, 193)
            Me.CcExempleProto1111.TabIndex = 0
            Me.CcExempleProto1111.Text = "CcExempleProto1111"
            '
            'Form12
            '
            Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
            Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
            Me.ClientSize = New System.Drawing.Size(284, 264)
            Me.Controls.Add(Me.CcExempleProto1111)
            Me.Name = "Form12"
            Me.Text = "Form12"
            Me.ResumeLayout(False)
     
        End Sub
        Friend WithEvents CcExempleProto1111 As WindowsApplication1.ccExempleProto111
    End Class
    Mais est-ce que ça te donne ce que tu veux en terme de perf ?

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Salut, je viens de faire quelques test, et sous windows, ça marche très bien, merci !
    pour info, voici le code utilisé :
    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
    55
    56
    57
    58
    59
    60
    61
     
    Public Class Form1
     
        Private bBuffer As Bitmap = Nothing
        Private dtStarted As Date = Now
     
        'pour compter le nombre de traçages entre chaque seconde
        Dim compteur_nb_pt_sec As Integer = 0
        Dim compteur_nb_pt_sec_old As Integer = 0
        Dim now_sec_old As Integer = 0
     
        Private ReadOnly Property Buffer() As Bitmap
            Get
                If bBuffer Is Nothing Then
                    ResetBuffer()
                End If
                Return bBuffer
            End Get
        End Property
     
        Private Sub ResetBuffer()
            bBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
            Dim MaFont As Font
            Dim MaBrush As Brush
     
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            If now_sec_old = Now.Second Then
                compteur_nb_pt_sec = compteur_nb_pt_sec + 1
            Else
                compteur_nb_pt_sec_old = compteur_nb_pt_sec
                compteur_nb_pt_sec = 0
            End If
            now_sec_old = Now.Second
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
            gd.DrawString(compteur_nb_pt_sec_old.ToString, MaFont, MaBrush, New Point(0, 0))
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, New Point(0, 50))
            gd.DrawString(Now.ToString, MaFont, MaBrush, New Point(0, 100))
     
            MaFont.Dispose()
            MaBrush.Dispose()
            gd.Dispose()
            Me.Refresh()
        End Sub
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(Me.Buffer, 0, 0)
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
     
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            ResetBuffer()
        End Sub
     
    End Class
    Et voici un code de test pour pocket pc qui marche bien :
    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
     
    Public Class Form1
     
        Private bBuffer As Bitmap = New Bitmap(Me.Width, Me.Height)
        Private dtStarted As Date = Now
        Dim compteur_nb_pt_sec As Integer = 0
        Dim compteur_nb_pt_sec_old As Integer = 0
        Dim now_sec_old As Integer = 0 
     
        Private Sub ResetBuffer()
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
            Dim MaFont As Font
            Dim MaBrush As Brush
     
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            'ici je compte le nombre d'affichage entre chaque seconde
            If now_sec_old = Now.Second Then
                compteur_nb_pt_sec = compteur_nb_pt_sec + 1
            Else
                compteur_nb_pt_sec_old = compteur_nb_pt_sec
                compteur_nb_pt_sec = 0
            End If
            now_sec_old = Now.Second
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
            gd.DrawString(compteur_nb_pt_sec_old.ToString, MaFont, MaBrush, 0, 0)
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, 0, 50)
            gd.DrawString(Now.ToString, MaFont, MaBrush, 0, 100)
     
            MaFont.Dispose()
            MaBrush.Dispose()
            gd.Dispose()
            gd = Nothing
        End Sub
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(bBuffer, 0, 0)
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
     
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            ResetBuffer()
            Me.Refresh()
        End Sub
     
    End Class
    Je tiens largement la cadence avec cette solution. Par contre, contrairement à ce que je pensais au début, dès que je fait un drawimage, je passe de 35hz à 20hz. Je continue de chercher de ce coté.
    En tout cas, merci olsimare pour ton aide
    PS : je n'ai pas réussi à intégrer ton contrôle

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Petite précision concernant mon affichage, je ne suis pas sur de m'etre bien exprimé : c'est un genre de tableau de bord que je réalise. En fait, je dessine un fond à partir d'un dessin, puis je viens afficher des traits, des ronds et du texte dessus.
    Ce qu'il faudrait, c'est de ne jamais avoir à redessiner le fond, et juste rafraichir ce que j'affiche dessus. Pour etre plus clair, imaginons que j'ai en fond une graduation de compteur, une solution pourrait etre de ne rafraichir que l'aiguille ... Est ce possible ?

  10. #10
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Bonjour.

    Tu crées ta bitmap de base qui contient le fond une et une seule fois dans le new (par exemple), et tu la mets dans bBuffer avant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Dim gd As Graphics = Graphics.FromImage(bBuffer)
    Ca doit le faire.

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Bonjour, j'avais essayé ça mais ça ne marche pas. En effet, quand je dessine sur gd, en fait il dessine sur bBuffer. C'est pour cette raison qu'on affiche bBuffer au final :
    e.Graphics.DrawImage(Me.Buffer, 0, 0)
    Me.Buffer retourne bBuffer
    Du coup, si je dessine plusieurs fois, il garde les tracés précédents.
    Ou alors ce n'est pas de cette façon dont tu parlais ?

  12. #12
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Bonjour.

    Citation Envoyé par proto111 Voir le message
    Ou alors ce n'est pas de cette façon dont tu parlais ?
    Gagné !

    Ce que je voulais dire c'est de créer UNE AUTRE bitmap pour contenir le fond.

    Cette bitmap est figée est tu la mets dans bBuffer (via un FromHBitmap par exemple) avec d'affecter bBuffer à ton Graphics.

    Exemple :
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    Option Explicit On
    Option Strict On
    Public Class Form5
     
        Private bBackgroundBuffer As Bitmap
        Private WithEvents t As New Timer
     
        Sub New()
            InitializeComponent()
            refreshBackGround()
            t.Interval = 100
            t.Start()
        End Sub
     
        Dim intNumberOfTick As Integer
        Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
            intNumberOfTick += 1
            Me.Invalidate()
        End Sub
     
        Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
            MyBase.OnSizeChanged(e)
            refreshBackGround()
        End Sub
     
        Dim intNumberOfRefresh As Integer
        Private Sub refreshBackGround()
            intNumberOfRefresh += 1
            bBackgroundBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBackgroundBuffer)
     
            Dim b As New _
            System.Drawing.Drawing2D.LinearGradientBrush(Me.ClientRectangle, _
            Color.Black, _
            Color.Black, _
            35, False)
            Dim cb As New System.Drawing.Drawing2D.ColorBlend()
            cb.Colors = _
                New Color() {Color.Red, _
                Color.Orange, _
                Color.Aqua, _
                Color.LightBlue, _
                Color.Blue}
     
            cb.Positions = _
            New Single() {0, 0.25, 0.5, 0.75, 1}
            b.InterpolationColors = cb
     
            gd.FillRectangle(b, Me.ClientRectangle)
     
            gd.Dispose()
        End Sub
     
        Dim fFont As Font = New Font("DS-Digital", 20, FontStyle.Italic)
        Dim bBrush As Brush = New SolidBrush(Color.White)
     
        Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As Boolean
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            Dim ip As IntPtr = bBackgroundBuffer.GetHbitmap
            Dim ibufferImage As Bitmap = Bitmap.FromHbitmap(ip)
            Dim gd As Graphics = Graphics.FromImage(ibufferImage)
            gd.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            gd.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
     
            gd.DrawString(Now.ToString, fFont, bBrush, New Point(0, 0))
            gd.DrawString("Refresh : " & intNumberOfRefresh.ToString, fFont, bBrush, New Point(0, 50))
            gd.DrawString("Tick : " & intNumberOfTick.ToString, fFont, bBrush, New Point(0, 100))
     
            e.Graphics.DrawImage(ibufferImage, 0, 0)
     
            DeleteObject(ip)
            gd.Dispose()
            ibufferImage.Dispose()
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        End Sub
     
    End Class
    EDIT : En passant, avec le fond que j'ai mis, tu prends 3Mo de mémoire utilisée de plus toutes les secondes si tu ne fais pas le DeleteObject ... J'avais laissé tourné le temps d'une cloppe et surprise 1.8 Go de mémoire utilisée ...

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Salut, alors j'ai essayé ta solution, mais c'est pire. Décidément, je pense que je n'obtiendrai jamais satisfaction avec cette méthode. Je commence à me tourner vers DirectX, mais un peu à contre coeur parce que ce n'était pas l'objectif, et que je ne suis pas sur que cette solution marche mieux ...
    En tout cas merci de ton aide olsimare, et je reste ouvert à toute solution !

  14. #14
    Membre chevronné
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 179
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 179
    Points : 1 776
    Points
    1 776
    Par défaut
    Bonjour.

    Citation Envoyé par proto111 Voir le message
    Salut, alors j'ai essayé ta solution, mais c'est pire.
    En terme de performance ? Super, plus on avance, plus on recule !

    Encore une piste à creuser, utiliser l'API BitBlt au lieu de faire un drawimage, ça devrait aller plus vite.

    Cdt.
    Bon à savoir : la touche F1 ne sert pas à commander des places pour le grand prix de Belgique.

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Bonjour,
    En terme de performance ? Super, plus on avance, plus on recule !
    oui en terme de performance ...
    En faisant des recherches hier soir, j'ai effectivement trouvé (ou plutot retrouvé, je m'en était deja servi) l'api BitBlt. Les avis ont l'air de divergé un peu par rapport à son utilisation en .NET, mais ça vaut le coup de tenter. J'ai vu aussi sur le site de msdn une loadimage.dll qui semble très rapide, mais pas moyen de mettre la main dessus. Sinon il y a des librairies graphiques développées par des programmeurs indépendants, mais c'est des vieux trucs, et niveau explication c'est limité !
    Je vais essayé BitBlt dans un premier temps.

Discussions similaires

  1. [Débutant] cumuler e.graphics.drawstring et e.graphics.drawimage
    Par jlp13012 dans le forum VB.NET
    Réponses: 4
    Dernier message: 15/07/2014, 11h33
  2. Formalisation graphique des algorithmes
    Par David R. dans le forum Algorithmes et structures de données
    Réponses: 14
    Dernier message: 08/12/2012, 10h21
  3. De la rapidité du code
    Par jfloviou dans le forum Contribuez
    Réponses: 233
    Dernier message: 29/05/2009, 02h17
  4. Réponses: 2
    Dernier message: 16/04/2007, 14h17
  5. Réponses: 10
    Dernier message: 27/08/2002, 23h24

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