Pourquoi dois-je augmenter J'ai besoin d'une solution pour obtenir le résultat exact. p> Même police, même texte utilisé dans les deux fonctions. < / p> de réponse par op: p> mon code. p> p> mesurstring () code> largeur de résultat de 21%
taille.Width = taille.Width * 1.21f; code>
Pour échapper à Word Wrap in Cordon () Code>?
7 Réponses :
Méthode MesureString () avait des problèmes, en particulier lors du dessin des caractères non-ASCII. S'il vous plaît essayez Textrenderer.Measuretext () à la place. P>
@Chocapicsz: Pour être honnête, je n'ai pas trouvé une méthode de mesure de limites de chaîne unique, quel que soit l'environnement de programmation ... La chose amusante est, le même texte, la même taille de police, mais une taille de police différente peut donner des résultats complètement différents. . J'ai une fois comparé l'anglais au rapport de chaîne traduit avec des résultats amusants: pour Arial 10, le texte traduit était plus large, mais pour Arial 18, il était plus étroit que le texte anglais ... c'est la ville.
Vous devez probablement ajouter les indicateurs suivants: StringFormat CODE> StringFormat CODE> XXX PRE> P>
besoin de mesurer la chaîne exactement, de ne pas autoriser la surface de positionnement extérieur surplomb
Cet article sur CodeProject donne deux façons d'obtenir la taille exacte des personnages comme ils sont rendus par cordon. p>
Non, seule la largeur, cela n'aide pas à la hauteur. Quoi qu'il en soit, c'est un mauvais article, car les graphismes.mesurecharacterranges ajoute réellement le rembourrage!
Il suffit d'utiliser le paramètre code> surcharge code> StringFormat CODE> StringFormat CODE> StringFormat CODE> StringFormat.Generictypographic code>) était suffisant pour mes besoins simples et sans largeur - Merci de lier à cet article!
Ugh, merci @THRACX. Je me demandais pourquoi Measurestring était si inexacte et je regarde toutes ces solutions, mais j'ai complètement manqué que j'avais négligé le paramètre StringFormat.
graphiques.mestring, textrenderer.metsetext et graphiques.Measurecharacterranges Tous renvoient une taille comprenant des pixels vides autour du glyphe pour accueillir des ascendeurs et des descendeurs.
En d'autres termes, ils renvoient la hauteur de "A" comme la même que la hauteur de "D" (ASCENDER) ou "Y" ( descender). Si vous avez besoin de la taille réelle du glyphe, le seul moyen est de dessiner la chaîne et de compter les pixels: p>
Cela semble inefficace, mais c'est vrai: ne pouvait pas le faire fonctionner avec aucune des fonctions, ils incluaient tous le rembourrage. Utilisera des bitmaps aussi. Merci!
Si cela aide tout le monde, j'ai transformé la réponse de Smirkingman à C #, fixant des bugs de mémoire (utilisation - disposer) et des pauses en boucle extérieure (pas de todos). J'ai également utilisé la mise à l'échelle sur les graphismes (et les polices), alors j'ai ajouté que cela aussi (n'a pas fonctionné autrement). Et il renvoie Rectanglef, car je voulais positionner le texte avec précision (avec graphiques.Drawtext).
Le pas-parfait mais assez bon pour mon but em> code source: p> static class StringMeasurer
{
private static SizeF GetScaleTransform(Matrix m)
{
/*
3x3 matrix, affine transformation (skew - used by rotation)
[ X scale, Y skew, 0 ]
[ X skew, Y scale, 0 ]
[ X translate, Y translate, 1 ]
indices (0, ...): X scale, Y skew, Y skew, X scale, X translate, Y translate
*/
return new SizeF(m.Elements[0], m.Elements[3]);
}
public static RectangleF MeasureString(Graphics graphics, Font f, string s)
{
//copy only scale, not rotate or transform
var scale = GetScaleTransform(graphics.Transform);
// Get initial estimate with MeasureText
//TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.NoClipping;
//Size proposedSize = new Size(int.MaxValue, int.MaxValue);
//Size size = TextRenderer.MeasureText(graphics, s, f, proposedSize, flags);
SizeF sizef = graphics.MeasureString(s, f);
sizef.Width *= scale.Width;
sizef.Height *= scale.Height;
Size size = sizef.ToSize();
int xLeft = 0;
int xRight = size.Width - 1;
int yTop = 0;
int yBottom = size.Height - 1;
// Create a bitmap
using (Bitmap image = new Bitmap(size.Width, size.Height))
{
image.SetResolution(graphics.DpiX, graphics.DpiY);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Near;
strFormat.LineAlignment = StringAlignment.Near;
// Draw the actual text
using (Graphics g = Graphics.FromImage(image))
{
g.SmoothingMode = graphics.SmoothingMode;
g.TextRenderingHint = graphics.TextRenderingHint;
g.Clear(Color.White);
g.ScaleTransform(scale.Width, scale.Height);
g.DrawString(s, f, Brushes.Black, new PointF(0, 0), strFormat);
}
// Find the true boundaries of the glyph
// Find left margin
for (; xLeft < xRight; xLeft++)
for (int y = yTop; y <= yBottom; y++)
if (image.GetPixel(xLeft, y).ToArgb() != Color.White.ToArgb())
goto OUTER_BREAK_LEFT;
OUTER_BREAK_LEFT: ;
// Find right margin
for (; xRight > xLeft; xRight--)
for (int y = yTop; y <= yBottom; y++)
if (image.GetPixel(xRight, y).ToArgb() != Color.White.ToArgb())
goto OUTER_BREAK_RIGHT;
OUTER_BREAK_RIGHT: ;
// Find top margin
for (; yTop < yBottom; yTop++)
for (int x = xLeft; x <= xRight; x++)
if (image.GetPixel(x, yTop).ToArgb() != Color.White.ToArgb())
goto OUTER_BREAK_TOP;
OUTER_BREAK_TOP: ;
// Find bottom margin
for (; yBottom > yTop; yBottom-- )
for (int x = xLeft; x <= xRight; x++)
if (image.GetPixel(x, yBottom).ToArgb() != Color.White.ToArgb())
goto OUTER_BREAK_BOTTOM;
OUTER_BREAK_BOTTOM: ;
}
var pt = new PointF(xLeft, yTop);
var sz = new SizeF(xRight - xLeft + 1, yBottom - yTop + 1);
return new RectangleF(pt.X / scale.Width, pt.Y / scale.Height,
sz.Width / scale.Width, sz.Height / scale.Height);
}
}
L'élimination du bitmap est une bonne suggestion, mais tous ces gotos roi «débutant». Vous auriez été mieux en train de passer simplement le code VB dans converter.telerik.com et ajout d'une utilisation 'Pour le bitmap.
@smirkingman Gotos Reek 'Beggyer', S'ils sont utilisés pour des sauts inconditionnels, mais ils sont ok si elles sont utilisées pour des pauses à boucle à plusieurs niveaux (identiques relevant de la déclaration de retour). Par exemple, si je réécris ce code dans Java, ce ne serait pas "goto" mais "casser" mot-clé. Lire la suite à en.wikipedia.org/wiki/goto#common_usage_patterns_of_goto
@peenut Je n'oublierai jamais de lire le célèbre papier de Dijkstra accueilPages.cwi.nl/ ~ Storm / Enseignement / Reader / Dijkstra68.pdf Quand j'étais un garçon, il a laissé une impression durable sur moi> ;-), mais ce n'est donc pas un lieu de débat
Pour ceux qui préfèrent C #, une solution beaucoup plus simple consiste simplement à coller le VB dans convertisseur.telerik.com - Il ajoute automatiquement tous les points-virgules, les accolades et sans aucun pied
Essayez cette solution: http://www.codeproject.com / Articles / 2118 / Bypass-Graphiques-MesureString-Limitation (trouvé sur https://stackoverflow.com/a/11708952/908936 )
Code: P >
static public int MeasureDisplayStringWidth(Graphics graphics, string text, Font font)
{
System.Drawing.StringFormat format = new System.Drawing.StringFormat ();
System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0, 1000, 1000);
var ranges = new System.Drawing.CharacterRange(0, text.Length);
System.Drawing.Region[] regions = new System.Drawing.Region[1];
format.SetMeasurableCharacterRanges (new[] {ranges});
regions = graphics.MeasureCharacterRanges (text, font, rect, format);
rect = regions[0].GetBounds (graphics);
return (int)(rect.Right + 1.0f);
}
Personnellement, la manière la plus efficace et ce que je recommande, a toujours été:
const TextFormatFlags _textFormatFlags = TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix | TextFormatFlags.PreserveGraphicsClipping;
// Retrieve width
int width = TextRenderer.MeasureText(element.Currency, Currencyfont, new Size(short.MaxValue, short.MaxValue), _textFormatFlags).Width + 1;
// Retrieve height
int _tempHeight1 = TextRenderer.MeasureText("_", Currencyfont).Height;
int _tempHeight2 = (int)Math.Ceiling(Currencyfont.GetHeight());
int height = Math.Max(_tempHeight1, _tempHeight2) + 1;
Montrer le code. Vous faites quelque chose de mal, le multiplicateur devrait être 1,0