.MeasureString() ungenau?

  • Allgemein

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von RushDen.

    .MeasureString() ungenau?

    Warum ist .MeasureString so ungenau? Ich versuche grad jeden Buchstaben einzelnd aus einer Textdatei auszulesen, damit ich ihn einzelnd färben kann, doch die Abstände sind sehr verschieden, obwohl ich alles mit .MeasureString() gemessen habe:

    VB.NET-Quellcode

    1. Static distance As Single = 100
    2. Dim Y As Single = 50
    3. Dim input As String = sr.ReadToEnd
    4. For item = 0 To input.Length - 1
    5. distance += .MeasureString(input(item), DefaultFont, 10).Width
    6. If input(item) = vbLf Then
    7. distance = 100
    8. Y += .MeasureString(input(item), New Font(Font.FontFamily, 10), 10).Height - 2
    9. End If
    10. If Not writenText.Count > item Then
    11. .DrawString(input(item), DefaultFont, Brushes.Black, New PointF(distance, Y))
    12. ElseIf writenText(item) = input(item) Then
    13. .DrawString(input(item), DefaultFont, Brushes.Green, New PointF(distance, Y))
    14. Else
    15. .DrawString(input(item), DefaultFont, Brushes.Red, New PointF(distance, Y))
    16. End If
    17. If item = writenText.Count Then
    18. Dim pen As New Pen(Brushes.Cyan, 3)
    19. .DrawLine(pen, distance, Y + 15, distance + .MeasureString(input(item), DefaultFont, 10).Width, Y + 15)
    20. End If
    21. Next


    Hab ich etwas falsch gemacht? oder gibts noch andere Alternativen wie ich mein Vorhaben umsetzen kann.

    Das ganze soll übrigens ein Programm zum Tippgeschwindigkeit messen werden, das Markieren von den richtig getippten/falsch getippten Buchstaben klappt, aber die Buchstaben werden halt so weit versetzt voneinander angezeigt
    Also ich habs mit MeasureCharacterRange versucht (zweite Methode)(Vorlage: codeproject.com/Articles/2118/…MeasureString-limitations) & es kam in beiden Fällen wieder zu ungenauen Ergebnissen..

    Wäre es "sauber" jedem Buchstaben einzelnd eine Standard "Distanz" zuzuweisen (z.B. in einer dictionary(of Char,Byte)) und diese dann in meiner Schleife anzuwenden?
    der Codeproject-Artikel behandelt doch genau dein Thema. Sicherlich ist die Info, die du dort findest, fundierter als alles, was hier die User gewissermaßen aus der Hüfte schießen können.

    Es würde mich allerdings wundern, wenn die dortige Lösung tatsächlich failt, wie du sagst. Eher tippe ich drauf, dass du iwas falsch anwendest.
    ZB sind die Messungen nur für genau die bei der Messung angegebenen Parameter korrekt.
    Wenn du dann beim Zeichnen annere Parameter verwendest (etwa das Stringformat nicht mit angibst, dann malt der natürlich was anneres, als was du gemessen hattest.
    Es kommt zu ähnlich Ergebnissen wie bei .MeasureString:

    VB.NET-Quellcode

    1. Private Function MeasureDisplayStringWidth(graphics As Graphics, text As String, font As Font) As Integer
    2. Dim format As New System.Drawing.StringFormat()
    3. Dim rect As New System.Drawing.RectangleF(0, 0, 1000, 1000)
    4. Dim ranges As System.Drawing.CharacterRange() = {New System.Drawing.CharacterRange(0, text.Length)}
    5. Dim regions As System.Drawing.Region() = New System.Drawing.Region(0) {}
    6. format.SetMeasurableCharacterRanges(ranges)
    7. regions = graphics.MeasureCharacterRanges(text, font, rect, format)
    8. rect = regions(0).GetBounds(graphics)
    9. Return CInt(Math.Truncate(rect.Right + 1.0F))
    10. End Function


    und

    VB.NET-Quellcode

    1. distance += MeasureDisplayStringWidth(e.Graphics, input(item), DefaultFont)


    statt .MeasureString(...) wie im obigen Code


    Habe auch versucht mit dem Stringformat rumzuspielen (bspweise LineAlignment geändert usw, hat aber nicht geholfen)

    VB.NET-Quellcode

    1. If Not writenText.Count > item Then
    2. .DrawString(input(item), DefaultFont, Brushes.Black, New PointF(distance, Y))
    3. ElseIf writenText(item) = input(item) Then
    4. .DrawString(input(item), DefaultFont, Brushes.Green, New PointF(distance, Y))
    5. Else
    6. .DrawString(input(item), DefaultFont, Brushes.Red, New PointF(distance, Y))
    7. End If


    Dort wird der String gezeichnet (bzw jeder Buchstabe einzelnd in einer Schleife)
    Distance steigt derzeit nach jedem Durchlauf um die gemessene Breite und ist standardmäßig auf 80