J'utilise "DGV.GetRowDisplayRectangle" pour déterminer la position d'une cellule afin de dessiner un rectangle par dessus elle et la (ou les) cellule(s) en dessous, ceci afin de donner une impression de merge sur certaines plages de mon DGV.
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
    Private Sub DataGridViewCalcul_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles DataGridViewCalcul.Paint
        ' On "fusionne" les cellules identiques sur plusieurs lignes
        Dim i, j, PremiereLigne, DerniereLigne, MaHauteur As Integer
        Dim MaFont As New Font(Me.DataGridViewCalcul.DefaultCellStyle.Font.Name, Me.DataGridViewCalcul.DefaultCellStyle.Font.Size, Me.DataGridViewCalcul.DefaultCellStyle.Font.Style, GraphicsUnit.Point)
        Dim rct3, rct4 As Rectangle
        Dim s3, s4 As SizeF
 
        PremiereLigne = Me.DataGridViewCalcul.FirstDisplayedScrollingRowIndex
        DerniereLigne = Me.DataGridViewCalcul.FirstDisplayedScrollingRowIndex + Me.DataGridViewCalcul.DisplayedRowCount(True) - 2
 
        For i = PremiereLigne To DerniereLigne
            j = i + 1
            If Equals(Me.DataGridViewCalcul.Item(1, i).Value, Me.DataGridViewCalcul.Item(1, j).Value) Then
 
                s3 = e.Graphics.MeasureString(Me.DataGridViewCalcul.Item(3, i).Value, Me.DataGridViewCalcul.Font)
                s4 = e.Graphics.MeasureString(Me.DataGridViewCalcul.Item(4, i).Value, Me.DataGridViewCalcul.Font)
                MaHauteur = Me.DataGridViewCalcul.Rows(i).Cells(0).Size.Height + Me.DataGridViewCalcul.Rows(j).Cells(0).Size.Height
 
                ' 2 lignes de suite sont sur un branchement identique,on regarde s'il y en a d'autres 
                While j <= DerniereLigne AndAlso Equals(Me.DataGridViewCalcul.Item(1, i).Value, Me.DataGridViewCalcul.Item(1, j + 1).Value)
                    j += 1
                    MaHauteur += Me.DataGridViewCalcul.Rows(j).Cells(0).Size.Height
                End While
 
                ' On détermine la taille des 2 rectangles à dessiner
                rct3.X = Me.DataGridViewCalcul.GetColumnDisplayRectangle(3, True).X
                rct3.Y = Me.DataGridViewCalcul.GetRowDisplayRectangle(i, True).Y
                rct3.Height = MaHauteur - 1
                rct3.Width = Me.DataGridViewCalcul.Rows(i).Cells(3).Size.Width - 1
                rct4.X = Me.DataGridViewCalcul.GetColumnDisplayRectangle(4, True).X
                rct4.Y = rct3.Y
                rct4.Width = Me.DataGridViewCalcul.Rows(i).Cells(4).Size.Width - 1
                rct4.Height = rct3.Height
 
                ' On dessine les rectangles
                If Equals(Me.DataGridViewCalcul.Item(3, i).Style.BackColor, Color.LightGray) Then
                    ' On doit dessiner en gris
                    ' colonne 3
                    With e.Graphics
                        .FillRectangle(Brushes.LightGray, rct3)
                        ' On met le texte dans le rectangle
                        .DrawString(Me.DataGridViewCalcul.Item(3, i).Value, MaFont, Brushes.Black, rct3.Left + (rct3.Width / 2) - (s3.Width / 2), rct3.Top + ((rct3.Height / 2) - (s3.Height / 2)))
                    End With
                    ' colonne 4
                    With e.Graphics
                        .FillRectangle(Brushes.LightGray, rct4)
                        ' On met le texte dans le rectangle
                        .DrawString(Me.DataGridViewCalcul.Item(4, i).Value, MaFont, Brushes.Black, rct4.Left, rct4.Top + ((rct4.Height / 2) - (s4.Height / 2)))
                    End With
                Else
                    ' On doit dessiner en blanc
                    ' colonne 3
                    With e.Graphics
                        .FillRectangle(Brushes.White, rct3)
                        ' On met le texte dans le rectangle
                        .DrawString(Me.DataGridViewCalcul.Item(3, i).Value, MaFont, Brushes.Black, rct3.Left + (rct3.Width / 2) - (s3.Width / 2), rct3.Top + ((rct3.Height / 2) - (s3.Height / 2)))
                    End With
                    ' colonne 4
                    With e.Graphics
                        .FillRectangle(Brushes.White, rct4)
                        ' On met le texte dans le rectangle
                        .DrawString(Me.DataGridViewCalcul.Item(4, i).Value, MaFont, Brushes.Black, rct4.Left, rct4.Top + ((rct4.Height / 2) - (s4.Height / 2)))
                    End With
                End If
            End If
        Next i
 
    End Sub
Tout cela marche super bien, après quelques "difficultés", plus de scintillement (merci encore Graffito et smyley), et plus de "trainées" lors du scrolling (euh, merci à moi même).
Il me reste cependant une petite m.... qui m'énerve au plus haut point.
Lorsque je fait du scrolling vers le bas (barre d'ascenceur descent, contenu du DGV remonte), aucun problème, les cellules mergées suivent et lorsque on arrive en haut à cheval sur 2 ligne mergées, le rectangle arrête de se dessiner et seule le contenu de la ligne restant visible apparait.
La ou ça ne marche pas super, c'est quand je fais du scrolling vers le haut (barre d'ascenceur monte, contenu du DGV descent).
Lorsque les cellules à "merger" sont sur la première ligne et la deuxième ligne visible, mon rectangle apparait sur la première ligne et l'entète du DGV au lieu de la première ligne et la seconde.
Dès que je scroll d'une ligne supplémentaire, tout redevient normal.
Le problème vient de GetRowDisplayRectangle qui dans un sens me renvoi une valeur correcte, et dans l'autre une valeur erronée de 12 points (ce qui correspond à la hauteur d'une ligne), j'ai mis un mouchard qui m'a permis de me rendre compte de ça.
Est-ce que quelqu'un a déjà eu ce problème?
Comment passer outre?

Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.