Graphics.DrawString() 的居中文本输出
-
08-06-2019 - |
题
我正在使用 .NETCF (Windows Mobile) Graphics
类和 DrawString()
方法将单个字符渲染到屏幕上。
问题是我似乎无法将其正确居中。无论我为字符串渲染位置的 Y 坐标设置什么,它总是低于该值,并且文本大小越大,Y 偏移量越大。
例如,在文本大小为 12 时,偏移量约为 4,但在文本大小为 32 时,偏移量约为 10。
我希望角色垂直占据它所绘制的矩形的大部分,并水平居中。这是我的基本代码。 this
正在引用它正在绘制的用户控件。
Graphics g = this.CreateGraphics();
float padx = ((float)this.Size.Width) * (0.05F);
float pady = ((float)this.Size.Height) * (0.05F);
float width = ((float)this.Size.Width) - 2 * padx;
float height = ((float)this.Size.Height) - 2 * pady;
float emSize = height;
g.DrawString(letter, new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular),
new SolidBrush(Color.Black), padx, pady);
是的,我知道我可以使用标签控件并用它来设置居中,但实际上我确实需要使用 Graphics
班级。
解决方案 3
通过结合我收到的建议,我得出了以下结论:
private void DrawLetter()
{
Graphics g = this.CreateGraphics();
float width = ((float)this.ClientRectangle.Width);
float height = ((float)this.ClientRectangle.Width);
float emSize = height;
Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular);
font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size);
SizeF size = g.MeasureString(letter.ToString(), font);
g.DrawString(letter, font, new SolidBrush(Color.Black), (width-size.Width)/2, 0);
}
private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize)
{
// Compute actual size, shrink if needed
while (true)
{
SizeF size = g.MeasureString(text, font);
// It fits, back out
if (size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.Name, (float)(font.Size * .9), font.Style);
oldFont.Dispose();
}
}
到目前为止,这一切都完美无缺。
我唯一要更改的是将 FindBestFitFont() 调用移至 OnResize() 事件,这样我就不会在每次绘制字母时都调用它。仅当控件大小发生变化时才需要调用它。为了完整性,我只是将其包含在函数中。
其他提示
我想为 StringFormat 对象再投一票。您可以简单地使用它来指定“中心,中心”,并且文本将在提供的矩形或点的中心绘制:
StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;
然而,CF 中存在一个问题。如果对两个值都使用 Center,则会关闭 TextWrapping。不知道为什么会发生这种情况,这似乎是CF的一个错误。
要对齐文本,请使用以下命令:
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf);
请注意,此处的文本在给定范围内对齐。在此示例中,这是 ClientRectangle。
绘制居中文本:
TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter |
TextFormatFlags.GlyphOverhangPadding);
确定填充区域的最佳字体大小有点困难。我发现的一种有效方法是反复试验:从大字体开始,然后反复测量字符串并缩小字体直至合适。
Font FindBestFitFont(Graphics g, String text, Font font,
Size proposedSize, TextFormatFlags flags)
{
// Compute actual size, shrink if needed
while (true)
{
Size size = TextRenderer.MeasureText(g, text, font, proposedSize, flags);
// It fits, back out
if ( size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.FontFamily, (float)(font.Size * .9));
oldFont.Dispose();
}
}
您可以将其用作:
Font bestFitFont = FindBestFitFont(g, text, someBigFont, sizeToFitIn, flags);
// Then do your drawing using the bestFitFont
// Don't forget to dispose the font (if/when needed)
您可以使用一个实例 StringFormat
对象传递到 DrawString
方法使文本居中。
这是一些代码。这假设您在表单或用户控件上执行此操作。
Graphics g = this.CreateGraphics();
SizeF size = g.MeasureString("string to measure");
int nLeft = Convert.ToInt32((this.ClientRectangle.Width / 2) - (size.Width / 2));
int nTop = Convert.ToInt32((this.ClientRectangle.Height / 2) - (size.Height / 2));
从您的帖子来看,听起来 ClientRectangle 部分(例如,您没有使用它)给您带来了困难。