使用 DrawString 将单个字符居中
Posted
技术标签:
【中文标题】使用 DrawString 将单个字符居中【英文标题】:Centering an individual character with DrawString 【发布时间】:2012-01-16 03:18:43 【问题描述】:我已经尝试了所有建议的使文本居中的方法,但在使单个字符居中时似乎无法获得我想要的结果。
我有一个矩形。在那个矩形中,我用 DrawEllipse 画了一个圆。现在我想使用相同的矩形和 DrawString 在圆内绘制一个字符,使其完全居中。
这是我的基本代码:
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
using (Graphics g = Graphics.FromImage(xImage))
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.FillEllipse(fillBrush, imageRect.X, imageRect.Y, imageRect.Width - 1, imageRect.Height - 1);
g.DrawString(Text, font, Brushes.White, imageRect, stringFormat);
文本水平居中...但垂直居中不正确。使用像大写“I”这样的对称字符,我发现字符的顶部总是比字符的底部更靠近矩形的边缘。距离可能至少增加了 50%。
我假设它为像小写“j”这样挂得更低的字符测量了足够的空间。但是,由于我正在尝试使用单个字母创建图形图标,因此我想要更精确的居中。
【问题讨论】:
您是否将 DrawString 方法的结果与 TextRenderer.DrawText 方法的结果与 HoriztonalCenter 和 VerticalCenter 的 TextFormatFlags 进行比较? 无复制。请注意,大写的 I 没有像 g 那样的下降。 我尝试了 TextRenderer.DrawText 并得到了类似的结果。 Hans:我的观点是,当我绘制没有下划线的字符时,它们以垂直居中的方式为不存在的下划线提供空白空间。因此,角色并没有真正居中。 我假设GDI没有办法做到这一点,所以我要做的是测量文本,创建一个测量大小的位图,在位图上绘制文本,锁定位,并获取实际包含数据(非透明像素)的子矩形的边界区域。然后在第一个 Rectangle 的中心位置位 blit 那个矩形。我认为应该可以工作,但性能会很糟糕。 【参考方案1】:虽然约翰·阿伦的回答很完美,但我想发布我的回答:
private void Form1_Paint(object sender, PaintEventArgs e)
// Set up string.
string measureString = "HelloWorld";
Font stringFont = new Font("Arial", 100, FontStyle.Regular, GraphicsUnit.Pixel);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 10.0F, 10.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(10, 10f + stringSize.Height / 12.0f));
这样的代码结果:
“HelloWorld”在红色框中垂直居中。
因为下降线的高度大约等于stringSize.Height
的1/6,由MeasureString
计算
|顶部填充 1/6
|词体 3/6
|单词下降 1/6
|底部填充 1/6
【讨论】:
【参考方案2】:使用GraphicsPath
完成大小计算。
public static void DrawCenteredText(Graphics canvas, Font font, float size, Rectangle bounds, string text)
var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
// Determine physical size of the character when rendered
var area = Rectangle.Round(path.GetBounds());
// Slide it to be centered in the specified bounds
var offset = new Point(bounds.Left + (bounds.Width / 2 - area.Width / 2) - area.Left, bounds.Top + (bounds.Height / 2 - area.Height / 2) - area.Top);
var translate = new Matrix();
translate.Translate(offset.X, offset.Y);
path.Transform(translate);
// Now render it however desired
canvas.SmoothingMode = SmoothingMode.AntiAlias;
canvas.FillPath(SystemBrushes.ControlText, path);
【讨论】:
这真是个天才。我试试看。 @ccnyou 是对的,这太完美了!我尝试使用MeasureString
,但没有任何运气。今天我找到了这个答案。问题是旧的,但问题是实际的。这立即修复了它!
非常酷! +1 - GraphicsPath 被低估了(连同标签..);-)
这应该引起更多关注,我为此搜索了几个小时:)【参考方案3】:
如果你使用
StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic);
你有
改为
希望对你有帮助
【讨论】:
请注意图像中的“g”未居中。我不是在寻找印刷居中,我不是在字符需要对齐的地方绘制单词。我正在绘制一个字符,并且无论它是哪个字符,我都希望它位于圆的正中心。想想平面设计师如何通过居中在 Photoshop 中制作图标。我需要以编程方式进行。 好吧,我输了,John Arlen 有完美的答案! 应该是StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic());以上是关于使用 DrawString 将单个字符居中的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Graphics::DrawString 绘制杂项字符?
如何对齐 SpriteBatch.DrawString 绘制的文本?