C# 测量和拉绳差
为什么我必须将C# 测量和拉绳差,c#,.net,string,graphics,C#,.net,String,Graphics,为什么我必须将MeasureString()结果宽度增加21% size.Width=size.Width*1.21f 要在DrawString()中避开换行符 我需要一个解决方案来得到准确的结果 两个函数使用相同的字体、相同的字符串格式和相同的文本 根据OP的回答: SizeF size = graphics.MeasureString(element.Currency, Currencyfont, new PointF(0, 0), strFormatLeft); size.Wid
MeasureString()
结果宽度增加21%
size.Width=size.Width*1.21f代码>
要在DrawString()
中避开换行符
我需要一个解决方案来得到准确的结果
两个函数使用相同的字体、相同的字符串格式和相同的文本
根据OP的回答:
SizeF size = graphics.MeasureString(element.Currency, Currencyfont, new PointF(0, 0), strFormatLeft);
size.Width = size.Width * 1.21f;
int freespace = rect.Width - (int)size.Width;
if (freespace < ImageSize) { if (freespace > 0) ImageSize = freespace; else ImageSize = 0; }
int FlagY = y + (CurrencySize - ImageSize) / 2;
int FlagX = (freespace - ImageSize) / 2;
graphics.DrawImage(GetResourseImage(@"Flags." + element.Flag.ToUpper() + ".png"),
new Rectangle(FlagX, FlagY, ImageSize, ImageSize));
graphics.DrawString(element.Currency, Currencyfont, Brushes.Black,
new Rectangle(FlagX + ImageSize, rect.Y, (int)(size.Width), CurrencySize), strFormatLeft);
SizeF size=graphics.MeasureString(element.Currency,Currencyfont,new PointF(0,0),strFormatLeft);
尺寸宽度=尺寸宽度*1.21f;
int freespace=rect.Width-(int)size.Width;
if(freespace0)ImageSize=freespace;else ImageSize=0;}
int FlagY=y+(CurrencySize-ImageSize)/2;
intflagx=(freespace-ImageSize)/2;
graphics.DrawImage(GetResourceImage(@“Flags.”+element.Flag.ToUpper()+“.png”),
新矩形(FlagX、FlagY、ImageSize、ImageSize));
图形.抽绳(element.Currency,Currencyfont,画笔.黑色,
新矩形(FlagX+ImageSize,rect.Y,(int)(size.Width),CurrencySize),strFormatLeft);
我的代码。MeasureString()方法有一些问题,尤其是在绘制非ASCII字符时。请尝试TextRenderer.MeasureText()。您可能需要在StringFormat
标志中添加以下内容:
StringFormatFlags.FitBlackBox
关于codeproject的文章提供了两种方法来获得由DrawString呈现的字符的精确大小 Graphics.MeasureString、textrender.MeasureText和Graphics.MeasureCharacterRanges
全部返回一个大小,该大小包括轮廓周围的空白像素,以容纳上升和下降
换句话说,它们返回的“a”的高度与“d”(上升)或“y”(下降)的高度相同。如果需要图示符的真实大小,唯一的方法是绘制字符串并计算像素数:
Public Shared Function MeasureStringSize(ByVal graphics As Graphics, ByVal text As String, ByVal font As Font) As SizeF
' Get initial estimate with MeasureText
Dim flags As TextFormatFlags = TextFormatFlags.Left + TextFormatFlags.NoClipping
Dim proposedSize As Size = New Size(Integer.MaxValue, Integer.MaxValue)
Dim size As Size = TextRenderer.MeasureText(graphics, text, font, proposedSize, flags)
' Create a bitmap
Dim image As New Bitmap(size.Width, size.Height)
image.SetResolution(graphics.DpiX, graphics.DpiY)
Dim strFormat As New StringFormat
strFormat.Alignment = StringAlignment.Near
strFormat.LineAlignment = StringAlignment.Near
' Draw the actual text
Dim g As Graphics = graphics.FromImage(image)
g.SmoothingMode = SmoothingMode.HighQuality
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
g.Clear(Color.White)
g.DrawString(text, font, Brushes.Black, New PointF(0, 0), strFormat)
' Find the true boundaries of the glyph
Dim xs As Integer = 0
Dim xf As Integer = size.Width - 1
Dim ys As Integer = 0
Dim yf As Integer = size.Height - 1
' Find left margin
Do While xs < xf
For y As Integer = ys To yf
If image.GetPixel(xs, y).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
xs += 1
Loop
' Find right margin
Do While xf > xs
For y As Integer = ys To yf
If image.GetPixel(xf, y).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
xf -= 1
Loop
' Find top margin
Do While ys < yf
For x As Integer = xs To xf
If image.GetPixel(x, ys).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
ys += 1
Loop
' Find bottom margin
Do While yf > ys
For x As Integer = xs To xf
If image.GetPixel(x, yf).ToArgb <> Color.White.ToArgb Then
Exit Do
End If
Next
yf -= 1
Loop
Return New SizeF(xf - xs + 1, yf - ys + 1)
End Function
Public共享函数MeasureStringSize(ByVal图形作为图形,ByVal文本作为字符串,ByVal字体作为字体)作为SizeF
'使用MeasureText获取初始估计值
将标志变暗为TextFormatFlags=TextFormatFlags.Left+TextFormatFlags.NoClipping
Dim proposedSize As Size=新大小(Integer.MaxValue,Integer.MaxValue)
Dim size As size=TextRenderer.MeasureText(图形、文本、字体、建议大小、标志)
'创建位图
将图像变暗为新位图(大小.宽度,大小.高度)
image.SetResolution(graphics.DpiX,graphics.DpiY)
作为新StringFormat的Dim标准格式
strFormat.Alignment=StringAlignment.Near
strFormat.LineAlignment=StringAlignment.Near
'绘制实际文本
尺寸g作为图形=图形。FromImage(图像)
g、 SmoothingMode=SmoothingMode.HighQuality
g、 TextRenderingHint=Drawing.Text.TextRenderingHint.AntiAliasGridFit
g、 透明(颜色:白色)
g、 抽绳(文本、字体、画笔、黑色、新点F(0,0)、标准格式)
'查找标志符号的真实边界
作为整数的Dim xs=0
尺寸xf为整数=尺寸.宽度-1
Dim ys作为整数=0
尺寸yf为整数=尺寸高度-1
'找到左边距
当xsxs时执行
对于y作为整数=y到yf
如果image.GetPixel(xf,y).ToArgb Color.White.ToArgb,则
退出Do
如果结束
下一个
xf-=1
环
“找到上页边距
当ysys时执行
对于x作为整数=xs到xf
如果image.GetPixel(x,yf).ToArgb Color.White.ToArgb,则
退出Do
如果结束
下一个
yf-=1
环
返回新的SizeF(xf-xs+1,yf-ys+1)
端函数
如果这对任何人都有帮助的话,我将答案从smirkingman转换为C#,修复内存错误(使用-Dispose)和外部循环中断(无TODO)。我还对图形(和字体)使用了缩放,所以我也添加了缩放(否则不起作用)。它返回矩形F,因为我想精确定位文本(使用Graphics.DrawText)
这不是完美的,但对我来说足够好的源代码:
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);
}
}
静态类StringMeasurer
{
私有静态SizeF GetScaleTransform(矩阵m)
{
/*
3x3矩阵,仿射变换(倾斜-旋转使用)
[X比例,Y倾斜,0]
[X倾斜,Y比例,0]
[X翻译,Y翻译,1]
索引(0,…):X比例、Y倾斜、Y倾斜、X比例、X平移、Y平移
*/
返回新的SizeF(m.Elements[0],m.Elements[3]);
}
公共静态矩形测量(图形、字体f、字符串s)
{
//仅复制缩放,不旋转或变换
var scale=GetScaleTransform(graphics.Transform);
//使用MeasureText获取初始估计值
//TextFormatFlags flags=TextFormatFlags.Left | TextFormatFlags.NoClipping;
//尺寸建议尺寸=新尺寸(int.MaxValue,int.MaxValue);
//大小大小=TextRenderer.MeasureText(图形、s、f、建议大小、标志);
SizeF SizeF=图形。测量(s,f);
sizef.Width*=刻度宽度;
sizef.高度*=刻度高度;
Size Size=sizef.ToSize();
int-xLeft=0;
int xRight=大小.宽度-1;
int-yTop=0;
int yBottom=大小。高度-1;
//创建位图
使用(位图图像=新位图(大小.宽度,大小.高度))
{
image.SetResolution(graphics.DpiX,graphics.DpiY);
StringFormat strFormat=新StringFormat();
strFormat.Alignment=StringAlignment.Near;
strFormat.LineAlignment=StringAlignment.Near;
//绘制实际文本
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);
}
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;