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.
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);
}
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);
}
}