C# GDI+如何正确获取单个字符角点并绘制外接矩形框
问题说明
我编写的C# GDI+绘图代码及当前输出如下:
现有代码:
Bitmap bitmap = new Bitmap(600, 300, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bitmap); GraphicsPath path = new GraphicsPath(); StringFormat format = new StringFormat(); Rectangle rect = new Rectangle(0, 0, 600, 300); SolidBrush Brush = new SolidBrush(Color.White); g.FillRectangle(Brush, rect); g.SmoothingMode = SmoothingMode.AntiAlias; format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; path.AddString(textBox1.Text, FontFamily.GenericSansSerif, (int)FontStyle.Bold, 128, rect, format); Brush = new SolidBrush(Color.Blue); g.FillPath(Brush, path); float x = path.GetBounds().X; float y = path.GetBounds().Y; float w = path.GetBounds().Width / textBox1.Text.Length; float h = path.GetBounds().Height; Pen redPen = new Pen(Color.Red, 2); for (int i = 0; i < textBox1.Text.Length+1; i++) { rect = new Rectangle((int)x, (int)y, (int)w*i, (int)h); g.DrawRectangle(redPen, rect); } pictureBox1.Image = bitmap;
问题原因
当前代码的实现逻辑存在错误:直接将整个字符串的总宽度按字符数平均分配,默认所有字符宽度相等,遇到非等宽字符(如中文、不同宽度的英文字母)时,计算出的矩形和实际字符位置不匹配,无法正确获取每个字符的角点坐标。
我需要为每个字符绘制并填充外接矩形,预期效果如下:
解决方案
将原逻辑改为逐个字符测量实际尺寸,再分别绘制字符和对应外接矩形即可,修改后代码如下:
Bitmap bitmap = new Bitmap(600, 300, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bitmap); StringFormat format = new StringFormat(); Rectangle totalRect = new Rectangle(0, 0, 600, 300); // 初始化背景 SolidBrush whiteBrush = new SolidBrush(Color.White); g.FillRectangle(whiteBrush, totalRect); g.SmoothingMode = SmoothingMode.AntiAlias; format.LineAlignment = StringAlignment.Center; string inputText = textBox1.Text; Font drawFont = new Font(FontFamily.GenericSansSerif, 128, FontStyle.Bold); // 计算字符串总宽度,实现整体居中对齐 SizeF totalTextSize = g.MeasureString(inputText, drawFont); float currentX = (totalRect.Width - totalTextSize.Width) / 2; float baseY = totalRect.Height / 2; SolidBrush textBrush = new SolidBrush(Color.Blue); Pen borderPen = new Pen(Color.Red, 2); // 逐个处理每个字符 for (int i = 0; i < inputText.Length; i++) { char currentChar = inputText[i]; // 测量当前字符实际宽高 SizeF charSize = g.MeasureString(currentChar.ToString(), drawFont); // 计算当前字符的外接矩形 RectangleF charBounds = new RectangleF(currentX, baseY - charSize.Height / 2, charSize.Width, charSize.Height); // 绘制字符 g.DrawString(currentChar.ToString(), drawFont, textBrush, charBounds.Location); // 绘制字符外接矩形 g.DrawRectangle(borderPen, charBounds.X, charBounds.Y, charBounds.Width, charBounds.Height); // 偏移X坐标到下一个字符起始位置 currentX += charSize.Width; } pictureBox1.Image = bitmap; // 释放GDI资源,避免内存泄漏 drawFont.Dispose(); whiteBrush.Dispose(); textBrush.Dispose(); borderPen.Dispose(); g.Dispose();
修改点说明:
- 废弃原逻辑中均分字符串宽度的错误计算方式,改为单独测量每个字符的实际尺寸
- 先计算整个字符串的总宽度,保证字符串整体居中,和原排版需求一致
- 每个字符的外接矩形完全匹配字符实际绘制位置,无偏移
- 补充了GDI资源释放逻辑,避免长期运行出现内存泄漏
内容的提问来源于stack exchange,提问作者AndrePer
相关产品推荐
相关产品推荐

