Question

Of course, the Graphics.MeasureString method is well-known to have padding problems, and so you use Graphics.MeasureCharacterRanges instead, but as you can see here:

MeasureCharacterRanges problem

It's not measuring quite correctly. Is this a problem with MeasureCharacterRanges or is it my code? How can I fix it?

Here's my code:

    'Draw the selection cursor
    If Me.Focused Then
        Dim cX As Integer = 1, cY As Integer = 5, c As Char
        For i As Integer = 0 To Me.SelectionStart - 1
            c = Me.Text(i)

            If c = ControlChars.CrLf Then
                cY += Me.Font.Height
            Else
                Dim w As Integer = MeasureCharacter(g, c, Me.Font).Width
                g.DrawRectangle(Pens.Black, cX, cY, w, Me.Font.Height) 'Draw a rectangle for debugging
                cX += w
            End If
        Next

        g.DrawLine(Pens.Black, cX, cY, cX, cY + Me.Font.Height)
    End If
End Sub

Protected Function MeasureCharacter(ByVal g As Graphics, ByVal c As Char, ByVal f As Font) As Size
    Dim cr() As CharacterRange = {New CharacterRange(0, 1)}
    Dim sfmt As New StringFormat()
    sfmt.FormatFlags = StringFormatFlags.MeasureTrailingSpaces
    sfmt.SetMeasurableCharacterRanges(cr)
    Return g.MeasureCharacterRanges(c.ToString(), f, Me.ClientRectangle, sfmt)(0).GetBounds(g).Size.ToSize()
End Function
Was it helpful?

Solution

Measuring the length of indiviual characters doesn't take into account the kerning that occurs between groups of characters, so the sum of the lengths of the characters will not equal the length of the string.

If you look at your example text, you can see the kerning between the "t" at the end of "Sprint" and the "T" at the start of "Textbox", the characters are moved closer together than you would expect given their individual lengths.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top