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 :

Dessin et gestion


Sujet :

VB.NET

  1. #1
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut Dessin et gestion
    Bonjour,
    J'ai une petite question en ce qui concerne la gestion de dessins.
    Je dessine environ 800 cases (qui sont des losanges), pour chaque j'ajoute dans une liste l'identifiant et des 4 point qui représentent le polygone.

    Je veux que quand je passe sur un losange il change de couleur. Actuellement je parcours ma liste et pour chaque case je teste si la souris est dedans avec un truc dans ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Private Function PointIsInPolygon(ByVal polygon() As Point, _
        ByVal target_point As Point) As Boolean
     
        Dim path As New GraphicsPath()
        path.AddPolygon(polygon)
     
        Return path.IsVisible(target_point)
    End Function
    Ensuite je redessine par dessus les cases un polygone plein...Et quand la souris rebouge on recommence a dessiner les 800 cases.

    Le problème c'est que c'est long et ça bug pas mal. Quelqu’un aurait une autre solution ?

  2. #2
    Membre Expert Avatar de hunteshiva
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Février 2010
    Messages
    1 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2010
    Messages : 1 069
    Par défaut
    Bonjour,

    je pense à 2 choses,

    soit faire un tableau de coordonnées des losanges et faire une routine qui tests si la souris passe dans la surface d'un des losanges
    (mais a mon avis pas très optimisé)

    Sinon tu peux essayer d'implémenter un événement "MouseOn" à chacun de tes losanges.
    Si ce sont des graphiques crées par le code, tu peux leur ajouter des événements.
    Après je ne suis pas spécialiste, visiblement c'est avec un "AddHandler" que tu pourrais le faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AddHandler myTextGenerator.OnTextChanged, AddressOf myTextGenerator_MonEvenement
    Voir ce lien

    Je dirais même que POL63 a montré que mon idée était réalisable dans ce post
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
           dim p as new picturebox
           uncontainer.controls.add(p) ' <- ici uncontainer = ta grande PictureBox
           addhandler p.click, addressof pct_click '<- tu ajoute l'événement à ta PictureBox

  3. #3
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Merci,
    Je doute que je puisse intégrer les Event, moi je dessine sur un bitmap ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
          graphic.DrawPolygon(Pens.Black, PointArray)

  4. #4
    Membre Expert Avatar de hunteshiva
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Février 2010
    Messages
    1 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2010
    Messages : 1 069
    Par défaut
    Quel est le but de ton dessin?
    une animation? faire une impression en définitif?

  5. #5
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    C'est comme une carte donc il n'y aura pas d'impression

  6. #6
    Membre Expert Avatar de hunteshiva
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Février 2010
    Messages
    1 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2010
    Messages : 1 069
    Par défaut
    Alors pourquoi ne pas passer par des "picturebox" dans une "picturebox_Mère" ?
    tu pourrais facilement gérer le passage de la souris avec les évents.

  7. #7
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    C'est des losanges et les picturesbox voila quoi et y'en a 800. Non ?

  8. #8
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    si ton projet n'est pas trop avancé et que tu as le temps, tu peux tester en wpf on peut y faire des controles de la forme qu'on veut et en théorie ca encaisse mieux la charge graphique (en pratique ca dépend ^^)

    si c'est pour un jeu, il y a xna 4 qui utilise totalement directX, mais ca doit être beaucoup plus compliqué de s'y mettre
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Je me rend compte que j'ai pas été très clair.
    J'ai une Picturebox avec une image (les 800 cases) dedans pour l'instant (c'est pas oblige que ça reste comme ça).

    Je veux dessiner sur cette picturebox mais des trucs qui ne restent pas longtemps du type une sélection ou un trait. Quel est le moyen le plus optimise ?

    Je me pose cette question vu que en 1 seconde c'est possible de dessiner puis effacer une centaine de traits par exemple. Mais tout cela en gardant le quadrillage dessous...

  10. #10
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    c'est bien ce que j'avais cru comprendre ...

    avec des controles c'est plus simple qu'en dessinant, par contre en windows forms 800 controles losanges n'est pas pensable, en wpf ca devrait être beaucoup plus faisable

    si tu veux rester en windows forms tu peux jeter un oeil sur la classe bufferedgraphics, qui permet un dessin instantané du buffer
    avec 800 bufferedgraphics ca devrait être performant, par contre ca va prendre en RAM, en objet GDI, et en temps de création (dans la limite de l'acceptable je pense)
    avec un peu de chance modifier les 800 d'un coup demanderait quelques dizaines de millisecondes
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Je comprends pas pourquoi 800 controles ? Y'en a qu'un avec 800 cases dessus.
    Actuellement je fais ça mais ça rame :
    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
     
    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
     
            Dim graphic As Graphics = PictureBox1.CreateGraphics
            PictureBox1.Refresh()
     
            Dim centerX As Integer = ((e.X \ 70) * 70) + cellWidth / 2
            Dim centerY As Integer = ((e.Y \ 35) * 35) + cellHeight / 2
     
            Dim PointArray As Point() = {New Point(centerX, centerY - (cellHeight / 2)),
                                       New Point(centerX + (cellWidth / 2), centerY),
                                       New Point(centerX, centerY + (cellHeight / 2)),
                                       New Point(centerX - (cellWidth / 2), centerY)
                                      }
     
            graphic.FillPolygon(Brushes.Green, PointArray)
    Et a chaque fois que ça bouge je dessine un poly vert et les 800 cases générés je les touche pas. Mais le refresh les redessine je crois :/ donc du coup ça sert a rien.

    Vous voyez mieux ou est le probleme ?

  12. #12
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    oui tu as un picturebox avec 800 cases mais tu auais pu faire 800 controles ca serait revenu au même en plus simple (sauf sur windows forms )

    alors avant de dessiner il faut comprendre le système de dessin des application windows forms
    chaque controle est géré par l'os, ils ont chacun un parent sauf le form
    windows prévient chaque form quand il doit se redessiner, les events paintbackground et paint sont alors levé, le form se dessine, et ensuite le form appellent ces event sur chaque controle enfant, en fournissant le graphics (e.Graphics sur l'event paint)
    chaque controle se dessine et demande à chaque controle enfant de se dessiner aussi etc...

    à chaque event paint, ca part de rien, et ca se dessine entièrement, pour un bouton, il y a un drawrectangle et un drawstring en gros
    par contre tout ce qui a été dessiné précédemment n'existe plus
    appeler .refresh (ou .update ou .invalidate) fait que l'event paint est appelé
    ajouté à cela que l'os fait que l'event paint peut etre appelé sans qu'il y ait de .Refresh, windows vista et 7 gèrent bien les applications windows forms avec une mise en cache dans directX, sur windows xp c'est plus violent, déplacer une fenetre au dessus d'une autre par exemple fait que l'event paint va être levé des centaines de fois sur la fenetre du dessous

    il convient de ne dessiner que dans l'event paint, et sur e.graphics (pas de creategraphics), sous peine de perdre le dessin sur un event de l'os, et de ne pas trop perdre de temps, sinon en cas de rafale de paint ca rame

    tu dois donc dessiner tes 800 cases sur chaque event paint, dans l'état où elles sont, qui donc être stocké
    un system.drawing.bufferedgraphics permet de dessiner, il a une propriété graphics, et quand on .render dessus ca redessiner instantanément ce qu'on a dessiné sur un autre graphics
    sur l'event paint tu peux donc faire un render de chaque bufferedgraphics sur e.graphics ce qui sera rapide
    pour la gestion du changement d'une image, sur le clic par exemple tu modifies un bufferedgraphics (.graphics.clear(white) puis dessin) puis tu fait .Refresh (ou .invalidate)
    tu peux aussi tenter de ne pas faire refresh et de faire render de la seule case ayant été modifiée sur .Creategraphics, si ca fonctionne c'est encore mieux
    et si paint est levé par l'os le rendu sera bon quand même
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #13
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Alors si j'ai bien compris je dessine une fois les 800 cases dans le bufferedgraphics, et à chaque paint je commence par utiliser le buffered pour remettre les cases et ensuite je rajoute par dessus style la sélection en cours, etc ?

  14. #14
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    je viens de réfléchir en moins idiot (car au début je disais d'utiliser 800 bufferedgraphics ^^)
    donc =>

    sur la classe du form :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private _buffer as system.Drawing.bufferedgraphics
    initialisation : (à faire quand le picturebox a sa taille, donc sur le form_load avec un peu de chance)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    _buffer = system.Drawing.BufferedGraphicsManager.Current.Allocate(pct.creategraphics, pct.clientrectangle)
    for i as integer = 1 to 800
       ' dessin des cases sur_buffer.graphics
    next
    _buffer.render
    event paint du picturebox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _buffer.render(e.graphics)
    pour le changement du dessin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    _buffer.graphics.Draw...  ' dessiner par dessus la case qu'on veut changer
    _buffer.render(pct.Creategraphics) ' à tenter
    pct.invalidate ' si la ligne du dessus n'est pas satisfaisante
    le buffer ne se vide pas, donc en redessinant juste la partie à redessiner ca ne touche pas au reste, et c'est super performant

    désolé pour les fausses pistes du coup, mais ca fait longtemps que j'ai pas bufferé

    NB : si le picturebox est redimensionné, il faut refaire allocate dans _buffer, et faire _buffer.Dispose avant
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  15. #15
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Aucun probleme,
    donc dans l'exemple les changement de dessins sont dessines dans le buffer avec les cases si j'ai bien compris. Il faudrait pas mieux mettre 2 buffer ? un qui reste toujours le même avec les cases et un autre par dessus avec les modifications ? Je sais pas si c'est possible : si l'un ne remplace pas l'autre ?

    Parce que la du coup si on veut supprimer qq chose qui est sur la case faut redessiner les 800 cases dans le buffer.

  16. #16
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    non
    tu dessines ton buffer

    XXXXXX
    XXXXXX
    XXXXXX

    si tu veux modifier une case seulement, tu redessines toute la case, mais pas les autres


    XXXXXX
    XXXXXX
    XXXXXX

    tu peux redessiner la case en rouge selon ses coordonnées puis faire .render
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  17. #17
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour gaetan13

    Bonjour,on ne dessine pas dans un event move tout d'abord .C'est dans le down que c'est fait generalement.
    Ensuite si tu veux faire du "hilighted when hovered" c.à.d "surbrillant quand survole" avec des figures dessinees alors la il vaut mieux faire un class Losange (ou triangle ou ellipse ou bezier....etc ) comme celui qui suit:
    -dote d'une List(of point) convertible en array "à la volee"...
    -cree lui-meme son losange si on lui donne le 1er point (ptDown)
    -se dessine et deplace lui-me ses points .
    -change de couleur quand il selectionne
    -se "hightlite" quanq il est survole.
    -grace à sa prop Region qui permet de le "HitTester"
    Enfin le DoubleBuffering du Form et du PicBox est active avec SetStyle
    La gestion de l'event Paint du PicBox doit etre optimise :
    -pour accelerer le dessin il ne faut dessiner que les figures "actuellement" visibles avec Graphics.IsVisible(RectangleFigure)....

    Pour plus de "precision" on travaille avec des PointF(single) et non des Point(integer)..............
    Code du class MyPolygon

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
     
    Imports System.Drawing.Drawing2D
     
    Public Class MyPolygon
        'pour les besoins du Region
        Private tempPath As GraphicsPath = Nothing
        Public Sub New()
            Me.m_Region = New Region()
            Me.Points = New List(Of PointF)
            Me.ColorNormal = Color.Black
            Me.ColorSel = Color.LightBlue
            Me.ColorSel = Color.LightGray
            Me.BrushPen = New SolidBrush(Me.ColorNormal)
            Me.Fill = New SolidBrush(Color.Red)
            Me.ID = ""
     
        End Sub
     
        Private m_ID As String
        Public Property ID() As String
            Get
                Return m_ID
            End Get
            Set(ByVal value As String)
                m_ID = value
            End Set
        End Property
     
        'Prop Region
        Private m_Region As Region
        Public ReadOnly Property Region() As Region
            Get
                If Me.Points.Count > 3 Then  'si au moins 4 pts
                    tempPath = New GraphicsPath
                    tempPath.AddPolygon(Me.Points.ToArray)
                    m_Region = New Region(tempPath)
     
                    'libere la ressource
                    tempPath.Dispose()
                End If
                Return m_Region
            End Get
        End Property
        Private m_Points As List(Of PointF)
        Public Property Points() As List(Of PointF)
            Get
     
                Return m_Points
            End Get
            Set(ByVal value As List(Of PointF))
                m_Points = value
            End Set
        End Property
        Private m_Fill As SolidBrush
        Public Property Fill() As SolidBrush
            Get
                Return m_Fill
            End Get
            Set(ByVal value As SolidBrush)
                m_Fill = value
            End Set
        End Property
        Private m_BrushPen As SolidBrush
        Public Property BrushPen() As SolidBrush
            Get
                Return m_BrushPen
            End Get
            Set(ByVal value As SolidBrush)
                m_BrushPen = value
            End Set
        End Property
        Private m_ColorNormal As Color
        Public Property ColorNormal() As Color
            Get
                Return m_ColorNormal
            End Get
            Set(ByVal value As Color)
                m_ColorNormal = value
            End Set
        End Property
        Private m_ColorSel As Color
        Public Property ColorSel() As Color
            Get
                Return m_ColorSel
            End Get
            Set(ByVal value As Color)
                m_ColorSel = value
            End Set
        End Property
        Private m_ColorHighlight As Color
        Public Property ColorHighlight() As Color
            Get
                Return m_ColorHighlight
            End Get
            Set(ByVal value As Color)
                m_ColorHighlight = value
            End Set
        End Property
        Private m_IsSelected As Boolean
        Public Property IsSelected() As Boolean
            Get
                Return m_IsSelected
            End Get
            Set(ByVal value As Boolean)
                m_IsSelected = value
                If m_IsSelected Then
                    Me.BrushPen = New SolidBrush(Me.ColorSel)
                Else
                    Me.BrushPen = New SolidBrush(Me.ColorNormal)
                End If
            End Set
        End Property
        Private m_IsHovered As Boolean
        Public Property IsHovered() As Boolean
            Get
                Return m_IsHovered
            End Get
            Set(ByVal value As Boolean)
                m_IsHovered = value
                If m_IsHovered Then
                    Me.BrushPen = New SolidBrush(Me.ColorHighlight)
                Else
                    Me.BrushPen = New SolidBrush(Me.ColorNormal)
                End If
            End Set
        End Property
     
        'se dessine lui-mele
        Public Sub Draw(ByVal g As Graphics)
     
            If m_Points.Count = 1 Then 'c'est le 1er point =>cree le polygone d'abord.... 
                CreatePoints()
            End If
     
            'draw the polygon 
            g.FillPolygon(Me.Fill, Me.Points.ToArray())
            g.DrawPolygon(New Pen(Me.BrushPen, 4.0), Me.Points.ToArray())
     
            'survole ? oui dessine le rectangle "bounds" du Region
            If Me.IsHovered Then
                Dim pendDash As Pen = New Pen(Color.Black, 1.0)
                pendDash.DashStyle = DashStyle.Custom
                pendDash.DashPattern = New Single(1) {4, 4}
                Dim rc(0) As RectangleF
                rc(0) = Me.Region.GetBounds(g)
                g.DrawRectangles(pendDash, rc)
                g.FillRegion(Brushes.Brown, Me.Region)
     
                'libere la ressource
                pendDash.Dispose()
            End If
     
     
     
        End Sub
     
        'Public Function PointIsInPolygon(ByVal target_point As PointF) As Boolean
        '    Dim path As New GraphicsPath()
        '    path.AddPolygon(Me.Points.ToArray())
        '    Dim b As Boolean = path.IsVisible(target_point)
        '    path.Dispose()
        '    Return b
        'End Function
     
        ' Deplacement
        Public Sub Move(ByVal dragDiff As SizeF)
     
            For i As Integer = 0 To Me.Points.Count - 1
                Me.Points(i) += dragDiff
            Next
     
        End Sub
        ' privee 
        Private Sub CreatePoints()
            ' define cells
            Dim cellWidth As Double = 50.0
            Dim cellHeight As Double = 50.0
            Dim centerX As Integer = 0.0
            Dim centerY As Integer = 0.0
            If Me.Points.Count = 1 Then
                centerX = ((Me.Points(0).X / 70) * 70) + cellWidth / 2
                centerY = ((Me.Points(0).Y / 35) * 35) + cellHeight / 2
     
                Me.Points.RemoveAt(0) ' supprime le ptDow
     
                'les 4 points du losange 
     
                Me.Points.Add(New Point(centerX, centerY - cellHeight / 2))
                Me.Points.Add(New Point(centerX + cellWidth / 2, centerY))
                Me.Points.Add(New Point(centerX, centerY + cellHeight / 2))
                Me.Points.Add(New Point(centerX - cellWidth / 2, centerY))
            End If
        End Sub
    End Class
    code du Form utilisateur avec un PictureBbox :

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
     
    Public Class frmLosange
        'polygon à creer
        Private pln As MyPolygon = Nothing
        Private myPolygons As List(Of MyPolygon) = New List(Of MyPolygon)
     
        'polygon selectionne
        Private plnSel As MyPolygon = Nothing
        '
        Private IsDown As Boolean = False
        'point clique
        Private ptDown As PointF = PointF.Empty
        'point en mouvement
        Private ptMove As PointF = PointF.Empty
     
     
     
        Public Sub New()
     
            ' Cet appel est requis par le concepteur.
            InitializeComponent()
     
            ' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
     
            ' Double-buffering
            Me.SetStyle(ControlStyles.DoubleBuffer, True)
            Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            Me.SetStyle(ControlStyles.UserPaint, True)
     
            ' Redraw when resized
            Me.SetStyle(ControlStyles.ResizeRedraw, True)
     
        End Sub
     
        Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
            ptDown = e.Location
     
            'Add Point avec RightButton 
            If pln Is Nothing And e.Button = Windows.Forms.MouseButtons.Right Then 'add point avec RightButton 
                pln = New MyPolygon()
                pln.Points.Add(ptDown)
                myPolygons.Add(pln)
                pln = Nothing
     
                'refresh drawing area
                Me.PictureBox1.Invalidate()
            End If
            'Selection avec avec LeftButton
            If e.Button = Windows.Forms.MouseButtons.Left Then
                If myPolygons.Count <> 0 Then
                    For Each pg As MyPolygon In myPolygons
                        If pg.Region.IsVisible(ptDown) Then
                            pg.IsSelected = True
                            plnSel = pg
                            IsDown = True
                            Exit For
                        End If
                    Next
                End If
            End If
     
        End Sub
     
        Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
            ptMove = e.Location
            Dim dragDiff As SizeF = SizeF.Empty
            Dim dx As Single
            Dim dy As Single
            If IsDown And e.Button = Windows.Forms.MouseButtons.Left Then 'Selection
                dx = ptMove.X - plnSel.Points(0).X
                dy = ptMove.Y - plnSel.Points(0).Y
                dragDiff = New SizeF(dx, dy)
                plnSel.Move(dragDiff)
                Me.PictureBox1.Invalidate()
            ElseIf myPolygons.Count <> 0 And e.Button = Windows.Forms.MouseButtons.None Then  'Hover
                For Each pg As MyPolygon In myPolygons
                    If pg.Region.IsVisible(ptMove) Then
                        pg.IsHovered = True
     
                        'refresh drawing area
                        Me.PictureBox1.Invalidate()
                    Else
                        pg.IsHovered = False
     
                        'refresh drawing area
                        Me.PictureBox1.Invalidate()
                    End If
                Next
     
            End If
     
        End Sub
     
     
     
     
        Private Sub PictureBox1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
            IsDown = False
            ptDown = Point.Empty
            ptMove = Point.Empty
            If plnSel IsNot Nothing Then
                plnSel.IsSelected = False
                plnSel = Nothing
            End If
     
            'refresh drawing area
            Me.PictureBox1.Invalidate()
        End Sub
     
        Private Sub PictureBox1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
            Dim g As Graphics = e.Graphics
     
            If myPolygons.Count = 0 Then
                g.Clear(Color.WhiteSmoke)
                Return
            End If
     
            'dessine uniquement les polygones "visibles" ....... dans picturebox 
            'pour accelerer le dessin....
            Dim rcFigure As RectangleF
            For Each p As MyPolygon In myPolygons
                rcFigure = p.Region.GetBounds(g)
                If g.IsVisible(rcFigure) Then
                    p.Draw(g)
                End If
     
            Next
        End Sub
    End Class
    Bon code....

  18. #18
    Membre émérite

    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Israël

    Informations forums :
    Inscription : Mars 2012
    Messages : 691
    Par défaut
    Salut

    proposition

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     Public Class Form1
        Private BufferredGraphic As BufferedGraphics
        Private CurrentContext As BufferedGraphicsContext
        Private WithEvents board As New PictureBox
        Private flagshow As Boolean
        Private WithEvents buttonshow As New Button
        Public Class losangedata
            Private points(4) As System.Drawing.Point
            Private colorlosange As Brush
            Public Property pointlosange() As Point()
                Get
                    Return points
                End Get
                Set(ByVal value As Point())
                    points = value
                End Set
            End Property
            Public Property lacolorlosange() As Brush
                Get
                    Return colorlosange
                End Get
                Set(ByVal value As Brush)
                    colorlosange = value
                End Set
            End Property
        End Class
        Private listlosange As New List(Of losangedata)
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            buttonshow.Location = New Point(10, 0)
            buttonshow.Text = "affiche"
            board.Width = ClientRectangle.Size.Width
            board.Height = ClientRectangle.Size.Height - buttonshow.Height
            board.Location = New Point(0, buttonshow.Height)
            board.BackColor = Color.LightGoldenrodYellow
            CurrentContext = BufferedGraphicsManager.Current
            BufferredGraphic = Me.CurrentContext.Allocate(board.CreateGraphics(), board.DisplayRectangle)
            BufferredGraphic.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            Me.Controls.Add(board)
            Me.Controls.Add(buttonshow)
            InitLosange()
            Windows.Forms.Cursor.Position = New Point(0, 0)
            flagshow = False
        End Sub
        Private Sub InitLosange()
            Dim leftpos, toppos, side As Integer
            side = 24
            leftpos = side \ 2
            toppos = 2
            For item As Integer = 0 To 799
                Dim thelosange As New losangedata
                thelosange.pointlosange(0).X = leftpos
                thelosange.pointlosange(0).Y = toppos
                thelosange.pointlosange(1).X = thelosange.pointlosange(0).X + side \ 2
                thelosange.pointlosange(1).Y = thelosange.pointlosange(0).Y + side \ 2
                thelosange.pointlosange(2).X = thelosange.pointlosange(0).X
                thelosange.pointlosange(2).Y = thelosange.pointlosange(1).Y + side \ 2
                thelosange.pointlosange(3).X = thelosange.pointlosange(0).X - side \ 2
                thelosange.pointlosange(3).Y = thelosange.pointlosange(1).Y
                thelosange.pointlosange(4) = thelosange.pointlosange(0)
                thelosange.lacolorlosange = Brushes.RoyalBlue
                listlosange.Add(thelosange)
                leftpos += side
                If item Mod 40 = 39 And item <> 0 Then
                    leftpos = side \ 2
                    toppos += side
                End If
            Next
        End Sub
        Private Sub DrawLosange()
            BufferredGraphic.Graphics.Clear(Color.LightGoldenrodYellow)
            For Each item As losangedata In listlosange
                BufferredGraphic.Graphics.FillPolygon(item.lacolorlosange, item.pointlosange)
            Next
            board_Paint(board, New PaintEventArgs(Me.BufferredGraphic.Graphics, board.DisplayRectangle))
        End Sub
     
     
     
        Private Sub board_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles board.MouseMove
            For Each item As losangedata In listlosange
                If e.X > item.pointlosange(3).X And e.X < item.pointlosange(1).X And e.Y > item.pointlosange(0).Y And e.Y < item.pointlosange(2).Y Then
                    BufferredGraphic.Graphics.FillPolygon(Brushes.Red, item.pointlosange)
                End If
     
            Next
            board_Paint(board, New PaintEventArgs(Me.BufferredGraphic.Graphics, board.DisplayRectangle))
        End Sub
     
        Private Sub board_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles board.Paint
            If flagshow Then
                BufferredGraphic.Render()
            End If

  19. #19
    Membre confirmé Avatar de gaetan13
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2010
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2010
    Messages : 90
    Par défaut
    Merci beaucoup, je vais étudier toute vos propositions.

    @Pol63 : Mais pour suivre votre exemple si on veut que cette case redevienne à son état normal... Faut tout redessiner, non ?

  20. #20
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    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 197
    Par défaut
    Citation Envoyé par gaetan13 Voir le message
    Merci beaucoup, je vais étudier toute vos propositions.

    @Pol63 : Mais pour suivre votre exemple si on veut que cette case redevienne à son état normal... Faut tout redessiner, non ?
    soit redessiner ce qui a changé en état normal soit tout redessiner si on ne veut pas vérifier l'état

    n'ayant pas tous les détails, on ne peut pas forcément vous convient la solution qui vous convient le mieux mais les pistes y menant
    en l'occurrence je n'e sais pas si vous voulez faire du drag drop, du highlight sur mousehover, ou du changement d'image sur clic/hittest, si vos cases contiennent quelque chose etc ...
    si vous voulez faire un buffer pour l'état normal en plus ca ne pose pas de soucis
    à noter qu'on peut aussi render un buffer sur le graphics d'un autre buffer

    ce qu'il y a retenir, drawstring/drawpolygon ou autre sont lents, render ne l'est pas, donc il faut minimiser les draws pour ne les faire que sur ce qu'il y a modifier
    un bufferedgraphics c'est comme une image dans paint, vous pouvez faire un cercle rouge, si vous dessiner un cercle vert sur le cercle rouge, on ne voit plus le cercle rouge, et ce sans refaire les éventuels autre cercles présents qui ne changeront pas de couleur
    l'event paint c'est l'inverse, ca efface tout l'image et après ca redessine, avec un buffer.render c'est comme ouvrir un .bmp plutot que de refaire les cercles chacun leur tour
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. Gestion de dessins Autocad/Catia/3dxml sous Java
    Par tenebriox dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 15/02/2012, 17h33
  2. Gestions évènements avec souris - Dessiner avec souris
    Par CosaNostra dans le forum Débuter
    Réponses: 10
    Dernier message: 23/01/2010, 10h05
  3. Dessiner en Flash + Gestion du scroll
    Par Rodrigue dans le forum Flash
    Réponses: 2
    Dernier message: 14/10/2007, 16h49
  4. gestion d'un joystick ...
    Par Anonymous dans le forum DirectX
    Réponses: 1
    Dernier message: 23/05/2002, 12h53

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