TextRenderer.MeasureText et Graphiques.MeasureString discordance dans la taille

Ce n'est pas un problème d'arrondi. Différence ~ 5 + pixels.

Chaîne de cas de Test: ""MACD (26,12,9) -0.000016"

e.Graphics.MeasureString("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)
TextRenderer.MeasureText("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)

Le résultat est toujours:

139.3942
134

Pourquoi y a-t-il tant de différence de taille? J'ai juste besoin du tour de largeur de la chaîne en dehors de la méthode de peinture. Mais il devrait correspondre à MeasureString ou vice versa.

23
demandé sur Aseem Gautam 2011-07-15 13:13:45

2 réponses

TextRenderer utilise GDI pour rendre le texte, alors que Graphics utilise GDI+. Les deux utilisent une méthode légèrement différente pour la disposition du texte de sorte que les tailles sont différentes.

Celui que vous devriez utiliser dépend de ce qui sera finalement utilisé pour dessiner réellement le texte. Si vous le dessinez avec GDI+ Graphics.DrawString, Mesurez en utilisant Graphics.MeasureString. Si vous dessinez en utilisant GDI TextRenderer.DrawText, mesurez en utilisant TextRenderer.MeasureText.

Si le texte est affiché dans un contrôle Windows Forms, il utilise TextRenderer Si UseCompatibleTextRendering est défini sur false (qui est la valeur par défaut).

En lisant entre les lignes de votre question, vous semblez utiliser TextRenderer parce que vous n'avez pas d'instance Graphics en dehors de l'événement Paint. Si c'est le cas, vous pouvez en créer un vous-même pour faire la mesure:

using( Graphics g = someControl.CreateGraphics() )
{
    SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

Si vous n'avez pas accès à un contrôle pour créer l'instance graphique, vous pouvez l'utiliser pour en créer un pour l'écran, ce qui fonctionne très bien à des fins de mesure.

using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
     SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
54
répondu Sven 2011-07-15 14:36:36

J'ai fait la classe suivante pour utiliser MeasureString en dehors de l'événement paint, et cela fonctionne plutôt bien.

public interface ITextMeasurer
    {
        SizeF MeasureString(string text, Font font, StringFormat format);
    }

    public class TextMeasurer : ITextMeasurer
    {
        private readonly Image _fakeImage;
        private readonly Graphics _graphics;

        public TextMeasurer()
        {
            _fakeImage = new Bitmap(1, 1);
            _graphics = Graphics.FromImage(_fakeImage);
        }

        public SizeF MeasureString(string text, Font font, StringFormat format)
        {
            return _graphics.MeasureString(text, font, int.MaxValue, format);
        }
    }
1
répondu Aseem Gautam 2011-07-15 14:24:14