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 :

Rectangle autour d'une partie de texte


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut Rectangle autour d'une partie de texte
    Bonjour à tous,

    mon objectif est de dessiner dans un datagridview un rectangle vert dans une des cellules autour d'un texte recherché.

    Pour l'instant je m’entraîne à dessiner ce rectangle autour des 4 caractères à partir du 5ieme dans la colonne 1 ligne 3 (c'est pour vérifier que mon algo de dessin marche bien).

    ça donne ce code là dans le PAINT du datagridview:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
             Dim Rect1 As Rectangle
            Dim SizePolice As SizeF
     
            SizePolice = e.Graphics.MeasureString(Me.DataGridViewPIPC.Item(1, 3).Value.ToString.Substring(5, 4), Me.DataGridViewPIPC.Item(1, 3).InheritedStyle.Font)
            Rect1.X = Me.DataGridViewPIPC.GetColumnDisplayRectangle(1, True).X + e.Graphics.MeasureString(Me.DataGridViewPIPC.Item(1, 3).Value.ToString.Substring(0, 5), Me.DataGridViewPIPC.Item(1, 3).InheritedStyle.Font).Width
            Rect1.Y = Me.DataGridViewPIPC.GetRowDisplayRectangle(3, True).Y + 4
            Rect1.Height = SizePolice.Height - 1
            Rect1.Width = SizePolice.Width
            e.Graphics.DrawRectangle(New Pen(Brushes.LightGreen, 2), Rect1)
    Ca marche bien quand la police est de style BOLD, mais comme mon DGV contient des lignes en BOLD, REGULAR, ITALIC, je ne comprend pas pourquoi mon rectangle est mal positionné et dimensionné (largeur trop grande de quelques pixel) quand c'est du REGULAR ou ITALIC.

    Quelqu'un a-t-il une idée, c'est comme si le e.graphic.measurestring ne fonctionnait correctement qu'avec du BOLD??

  2. #2
    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 sibama

    Il faudrait travailler :
    -l'event CellPainting
    -le class CharacterRange qui sait obtenir le layoutRect de chaque sous-chaine ...
    Le code exemple du class teststring binde au dgv(illistration)

    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
     
     
     
    Public Class TestString
        Public Sub New(ByVal tl As String)
            Title = tl
     
        End Sub
        Public Property Title() As String
     
    End Class
    Public Class TestStrings
        Inherits List(Of TestString)
        Dim t As TestString
        Public Sub New()
     
     
            For i As Integer = 1 To 10
     
                t = New TestString("Smith Associted and Company Smith Associted and Company" + i.ToString())
     
                Me.Add(t)
            Next
     
        End Sub
    End Class
    le code du winform avec un dgv dessus:
    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
     
    Public Class frmDGVPaint
        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim l As TestStrings = New TestStrings()
     
            Dim bds As BindingSource = New BindingSource()
            bds.DataSource = l
            Me.dgv.DataSource = bds
        End Sub
        Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgv.CellPainting
     
            If Me.dgv.Columns("Title").Index = e.ColumnIndex AndAlso e.RowIndex >= 0 Then
     
     
                If e.Value IsNot Nothing Then
                    ' Check for the string  in the cell.
                    Dim s As String = CType(e.Value, String)
                    Dim fnt As Font = e.CellStyle.Font
     
                    'bounds du cell
                    Dim layoutRect As RectangleF = New Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, _
                    e.CellBounds.Width - 4, e.CellBounds.Height - 4)
     
     
                    ' Set character ranges 
                    Dim characterRanges As CharacterRange() = _
                    {New CharacterRange(0, 4), New CharacterRange(5, 4)}
     
                    ' Set string format.
                    Dim fmt As New StringFormat(StringFormat.GenericDefault)
                    fmt.SetMeasurableCharacterRanges(characterRanges)
     
                    ' Measure two ranges in string (obtient les regions de decoupage des sous-chaines).
                    Dim strRegions() As Region = e.Graphics.MeasureCharacterRanges(s, _
             fnt, layoutRect, fmt)
                    Dim g As Graphics = e.Graphics
     
                    'clipper les limites de dessin
                    g.Clip = New Region(e.CellBounds)
     
     
                    ' Redssine toute la cellule(hard way de l'api).
     
                    g.FillRectangle(Brushes.White, e.CellBounds)
                    ' je t'epargne ces lignes(voir exemple msdn)
                    ' Draw the grid lines (only the right and bottom lines;
                    ' DataGridView takes care of the others).
     
     
                    ' Draw text
                    g.DrawString(CStr(e.Value), e.CellStyle.Font, _
                   Brushes.Black, layoutRect.X + 2, layoutRect.Y + 2, _
                   fmt)
     
                    ' Draw rectangle pour la 1ere s/chaine .
                    Dim measureRect1 As RectangleF = _
                    strRegions(0).GetBounds(e.Graphics)
                    g.DrawRectangle(New Pen(Brushes.Yellow, 1), _
                    Rectangle.Round(measureRect1))
     
                    ' Draw rectangle pour la 2ere s/chaine(la tienne) .
                    Dim measureRect2 As RectangleF = _
                    strRegions(1).GetBounds(e.Graphics)
                    g.DrawRectangle(New Pen(Color.Red, 1), _
                    Rectangle.Round(measureRect2))
     
     
                    e.Handled = True
     
                End If
            End If
     
        End Sub
     
     
        Private Sub DataGridView1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles dgv.Paint
            'Dim Rect1 As Rectangle
            'Dim SizePolice As SizeF
     
            'SizePolice = e.Graphics.MeasureString(Me.DataGridViewPIPC.Item(1, 3).Value.ToString.Substring(5, 4), Me.DataGridViewPIPC.Item(1, 3).InheritedStyle.Font)
            'Rect1.X = Me.DataGridViewPIPC.GetColumnDisplayRectangle(1, True).X + e.Graphics.MeasureString(Me.DataGridViewPIPC.Item(1, 3).Value.ToString.Substring(0, 5), Me.DataGridViewPIPC.Item(1, 3).InheritedStyle.Font).Width
            'Rect1.Y = Me.DataGridViewPIPC.GetRowDisplayRectangle(3, True).Y + 4
            'Rect1.Height = SizePolice.Height - 1
            'Rect1.Width = SizePolice.Width
            'e.Graphics.DrawRectangle(New Pen(Brushes.LightGreen, 2), Rect1)
        End Sub
     
     
     
     
     End Class
    bon code...

  3. #3
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    Bonjour MABROUKI et merci pour ta réponse, désolé pour le temps mis pour te répondre mais j'étais sur un autre problème pour préparer les données pour pouvoir les passer dans le CharacterRange en fonction du contenu de ma textbox de recherche.

    3 petites questions (je sais j'abuse):
    - est-ce que la classe TestStrins a un intérêt particulier par rapport au contenu de la cellule du DGV convertit en ToString?
    - quand je passe ton exemple dans mon DGV, cela encadre bien les zones de texte (en tenant compte du style cette fois-ci) mais le reste du DGV reste noir (quand je dis reste c'est toute la partie qui est "dessinée" après la cellule concernée). Par contre, si je clique sur ces cellules "noir", l'événement Paint doit être activé et le texte de la cellule cliqué réapparaît.
    - Quel est l'intéret de passer par le DGV_CellPainting plutôt que dans le DGV_Paint?

  4. #4
    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
    re

    est-ce que la classe TestStrins a un intérêt particulier par rapport au contenu de la cellule du DGV convertit en ToString?
    Non c'est juste un exemple simple pour illustrer un formattage avec CharacterRange......
    Quel est l'intéret de passer par le DGV_CellPainting plutôt que dans le DGV_Paint?
    c'est le moyen "propre" recommande par l'api du dgv
    referes toi à ce topic msdn:
    How to: Customize the Appearance of Cells in the Windows Forms DataGridView Control

    Dans le code communique il y a 2 choses à rectifier :
    1/un boggus perso :la ligne ou il y a g.clip est à virer.Car dgv s'en charge en interne.Cette ligne explique le "fameux noir" que tu vois...

    2/StringFormat :est utilise pour recuperer les regions,mais alors nous intervenons dans le formatage du dgv...
    Il faut dans ce cas imiter jusqu'au bout ce qu'aurait fait dgv pour cela:
    -il faut rajouter 2 lignes au niveau du stringformat..
    -rectifier le layoutrec (rectangle englobant de drawstring)

    code revu:

    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
     
    Public Class frmDGVPaint
        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim l As TestStrings = New TestStrings()
     
            Dim bds As BindingSource = New BindingSource()
            bds.DataSource = l
            Me.dgv.DataSource = bds
        End Sub
        Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgv.CellPainting
     
            If Me.dgv.Columns("Title").Index = e.ColumnIndex AndAlso e.RowIndex >= 0 Then
     
     
                If e.Value IsNot Nothing Then
                    ' Check for the string  in the cell.
                    Dim s As String = CType(e.Value, String)
                    Dim fnt As Font = e.CellStyle.Font
     
                    'bounds du cell
                    Dim layoutRect As RectangleF = New Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, _
                    e.CellBounds.Width - 4, e.CellBounds.Height - 4)
     
     
                    ' Set character ranges 
                    Dim characterRanges As CharacterRange() = _
                    {New CharacterRange(0, 4), New CharacterRange(5, 4)}
     
                    ' Set string format.
                    Dim fmt As New StringFormat(StringFormat.GenericDefault)
                    fmt.SetMeasurableCharacterRanges(characterRanges)
                    '----------MODIF...........
                    'RAJOUT CECI CAR DGV PAR DEFAUT METS DES ELLIPSIS.....
                    fmt.Trimming = StringTrimming.EllipsisWord
                    fmt.Alignment = StringAlignment.Center
     
                    ' Measure two ranges in string (obtient les regions de decoupage des sous-chaines).
                    Dim strRegions() As Region = e.Graphics.MeasureCharacterRanges(s, _
             fnt, layoutRect, fmt)
                    Dim g As Graphics = e.Graphics
     
                    '----------MODIF...........
                    ' SUPPRIMER CETTE LIGNE :boggus
                    '(dgv clippe les limites dessin de lui meme)
                    'g.Clip = New Region(e.CellBounds)
     
     
                    ' Redssine toute la cellule(hard way de l'api).
     
                    g.FillRectangle(Brushes.White, e.CellBounds)
                    ' je t'epargne ces lignes(voir exemple msdn)
                    ' Draw the grid lines (only the right and bottom lines;
                    ' DataGridView takes care of the others).
     
                    '----------MODIF...........
                    ' Remplacer layoutRect => LA MISE EN FOMRE EST PRIS CHARGE 
                    ' PAR NOS SOINS -centre & ellipsis
                    ' Draw text
                    g.DrawString(CStr(e.Value), e.CellStyle.Font, _
                   Brushes.Black,
                   layoutRect, _
                   fmt)
     
     
                    ' Draw rectangle pour la 1ere s/chaine .
                    Dim measureRect1 As RectangleF = _
                    strRegions(0).GetBounds(e.Graphics)
                    g.DrawRectangle(New Pen(Brushes.Yellow, 1), _
                    Rectangle.Round(measureRect1))
     
                    ' Draw rectangle pour la 2ere s/chaine(la tienne) .
                    Dim measureRect2 As RectangleF = _
                    strRegions(1).GetBounds(e.Graphics)
                    g.DrawRectangle(New Pen(Color.Red, 1), _
                    Rectangle.Round(measureRect2))
     
     
                    e.Handled = True
     
                End If
            End If
     
        End Sub
    Cette fois cela devrait marcher ...
    bon code...

  5. #5
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    Merci pour tes explications, après adaptation de ton code à mon système de recherche (qui peut rechercher plusieurs mots dans une cellule) et au fait que plutôt que de dessiner un rectangle autour du texte je suis passé à l'option dessiner un rectangle plein sous le texte, j'obtiens le code suivant:
    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
     Private Sub DataGridViewPIPC_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridViewPIPC.CellPainting
     
            ' Gestion des zones de texte recherchées
            If SauvegardeRecherche.CountItem > 0 Then
                ' Vérification si la cellule est celle de la recherche en cours  
                Dim ColonneCellule As Integer = SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).Adresse.Colonne
                Dim LigneCellule As Integer = SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).Adresse.Ligne
                If ColonneCellule = e.ColumnIndex AndAlso e.RowIndex = LigneCellule Then
                    ' Récupération de la police
                    Dim MaPolice As Font = e.CellStyle.Font
                    ' Limites de la cellule
                    Dim MaTailleCellule As RectangleF = New Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 5, e.CellBounds.Height - 6)
                    ' Récupération des zones de texte à encadrer
                    Dim ZoneDeTexte As CharacterRange() = {New CharacterRange(SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).ZoneTexte(0).IndexDepart, SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).ZoneTexte(0).LongueurZone)}
                    For i = 1 To SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).CountZone - 1
                        ReDim Preserve ZoneDeTexte(i)
                        ZoneDeTexte(i) = New CharacterRange(SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).ZoneTexte(i).IndexDepart, SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).ZoneTexte(i).LongueurZone)
                    Next
                    ' Format de la chaine
                    Dim MonFormat As New StringFormat(StringFormat.GenericDefault)
                    MonFormat.SetMeasurableCharacterRanges(ZoneDeTexte)
                    MonFormat.Trimming = StringTrimming.EllipsisWord
                    MonFormat.Alignment = StringAlignment.Near
                    ' Obtention des regions de découpage des sous-chaines
                    Dim strRegions() As Region = e.Graphics.MeasureCharacterRanges(CStr(e.Value), MaPolice, MaTailleCellule, MonFormat)
                    Dim g As Graphics = e.Graphics
                    ' Redessine toute la cellule(hard way de l'api).
                    g.FillRectangle(Brushes.White, e.CellBounds)
                    ' Draw rectangle pour la 1ere s/chaine .
                    For i = 0 To SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).CountZone - 1
                        Dim measureRect1 As RectangleF = strRegions(i).GetBounds(e.Graphics)
                        g.FillRectangle(Brushes.LightGreen, strRegions(i).GetBounds(e.Graphics))
                    Next
                    g.DrawString(CStr(e.Value), e.CellStyle.Font, Brushes.Black, MaTailleCellule, MonFormat)
     
                    e.Handled = True
     
                End If
            End If
        End Sub
    Ca marche presque bien, il y a juste un problème sur le fait qu'il faut cliquer sur la cellule pour que le dessin apparaisse (ou disparaisse lorsque la recherche suivante est appliquée).

    J'ai bien essayé de mettre un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            Me.DataGridViewPIPC.UpdateCellValue(e.ColumnIndex, e.RowIndex)
    mais si ça fait bien disparaître l'ancien surlignage sur la recherche précédente, il faut toujours que je clique sur la nouvelle cellule trouvée pour voir mon dessin apparaître (la partie rectangle vert)??...

    Tu as une idée? d'autant que ça marche parfaitement si je fais apparaître la cellule recherchée par un scrolling de mon DGV.

  6. #6
    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
    Re

    Bah,avec ta condition sur ton list SauvegardeRecherche.CountItem > 0 c'est pas suffisant ...
    Il faudrait que tu memorise :
    - le "compte" de la recherche courante(proprement initialisee...)
    - le "compte" de la derniere recherche (qui doit etre maj)
    - faire un test pour verifier si "compte" de recherche courante est >0 et s'il differe de la derniere recherche.....avant de peindre


    Dans ce genre ,en l'absence de plus d'information :
    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
     
    Private lastCount As Integer
     Private SauvegardeRecherche As List(Of String)
     Private currentCount As Integer = SauvegardeRecherche.Count
     Private Sub dgv_CellPainting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgv.CellPainting
     
            ' Gestion des zones de texte recherchées
            If currentCount > 0 And currentCount <> lastCount Then
                'mettre à jour lastcount
                lastCount = SauvegardeRecherche.Count
     
                ' Vérification si la cellule est celle de la recherche en cours  
                Dim ColonneCellule As Integer = SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).Adresse.Colonne
                Dim LigneCellule As Integer = SauvegardeRecherche.Item(SauvegardeRecherche.Pointeur).Adresse.Ligne
     
               '.................reste du code....
     
    end sub

    si tu fais la recherche de l'exterieur c'est plus simple il suffit d'appeler
    dgv.UpdateCellValue,celui-ci declenche l'event CellPainting de lui -meme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
            Me.dgv.UpdateCellValue(ColonneCellule, LigneCellule) 
    End Sub
    bon code.........

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VBA-E] Mettre en gras une partie du texte d'une cellule
    Par clochardevobsy dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 05/05/2006, 17h25
  2. [JTextField] Supprimer une partie du texte
    Par jean_bobi dans le forum Composants
    Réponses: 4
    Dernier message: 26/09/2005, 16h22
  3. [VBA][Excel]Supprimer une partie du texte d'une grosse liste
    Par annedeblois dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 19/09/2005, 18h15
  4. Selectionner par javascript une partie de texte
    Par Oluha dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 30/06/2005, 17h53
  5. comment remplacer une partie de texte dans un champs
    Par patlapi dans le forum Paradox
    Réponses: 4
    Dernier message: 20/11/2003, 15h38

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