c# - 如何确定将在矩形中绘制的文本的高度?

标签 c# winforms gdi+

我正尝试在带有 GDI+ 的矩形中绘制一些文本,如这篇 Microsoft 文章中所述:https://msdn.microsoft.com/en-us/library/baw6k39s(v=vs.110).aspx .

指定我想要的宽度后,文本会自动换行到预期的下一行。问题是,我需要设置矩形的高度,使文本完全适合框内,没有被截断但没有额外的空白。在这种情况下,使用值进行试错测试根本行不通,因为文本会发生变化。

我实现了一个解决方案,通过向文本添加换行符然后测量高度来模拟渲染时发生的文本中断。但这似乎不起作用,并且框的高度通常有大量尾随空白(这似乎与文本量呈正线性关系)。

问题:

enter image description here

我的代码如下:

public void setBreakLen() { //determines how many chars fit on each line (note: using a FIXED WIDTH FONT) 
  double cwidth = TextRenderer.MeasureText("h", font).Width;
  breakLen = (int)((double)box.Width / (double)cwidth);
}



public void updateHeight() { //should tell me what the height of the box should be to fit perfectly
  StringBuilder sb = new StringBuilder(text);
  int numAppended = 0;
  for (int i = 0; i < text.Length; i++) {
      if ((i + 1) % breakLen == 0) {
          sb.Insert((i + 1 + numAppended), "\n");
          numAppended += 1;
       }
   }

   Size s = TextRenderer.MeasureText(sb.ToString(), font);
   height = s.Height;
   box = new Rectangle(x, y, width, height);
}

然而,这似乎有点矫枉过正,必须有更好的方法。 因此,我想这实际上是一个由两部分组成的问题。

  1. 如何使我当前的解决方案发挥作用?
  2. 有没有更好的办法 做这个?

注意: 使用调试器,我确定 breaklen 变量是正确的。它读作 11,每行有 11 个字符。

我还用固定宽度字体(Consolas 系列)检查了其他字符,它们都产生相同的中断长度。这是 StringBuilder 如何处理换行符的问题吗?我通常使用 Java 而不是 C#,所以我不熟悉流等。

编辑: 绘制代码如下:

g2d.DrawString(m.text, m.font, Brushes.Blue, m.box);
g2d.DrawRectangle(Pens.Black, Rectangle.Round(m.box));

编辑 2: 我已经尝试使用 MeasureText 函数的重载 Size 参数来实现这个辅助解决方案。尽管字符串很长,但每次都只返回 19,它似乎为单行返回了正确的高度。

    Size s = TextRenderer.MeasureText(text, font, new Size(width, 0));//i also tried MaxInt
    height = s.Height;
    Console.WriteLine(height);
    box = new Rectangle(x, y, width, height);

最佳答案

试试下面的代码。我只是将代码合并到一个函数中以使其运行。你可以看到变化。您必须使用 MeasureString 而不是 MeasureText。看看我得到的输出 enter image description here

Font font = new Font(FontFamily.GenericSansSerif, 12.0F, FontStyle.Bold);

int x = 10, y = 10, width = 120, height = 30, breakLen = 0;
Rectangle box;
string text = "THIS BOX IS TOO TALL!!!";

private void DrawRectangle()
{
    box = new Rectangle(x, y, width, height);

    using (Graphics g = this.CreateGraphics())
    {
        double cwidth = g.MeasureString("h", SystemFonts.DefaultFont).Width;
        breakLen = (int)((double)box.Width / (double)cwidth);

        StringBuilder sb = new StringBuilder(text);
        int numAppended = 0;

        for (int i = 0; i < text.Length; i++)
        {
            if ((i + 1) % breakLen == 0)
            {
                sb.Insert((i + 1 + numAppended), "\n");
                numAppended += 1;
            }
        }

        Size s = TextRenderer.MeasureText(sb.ToString(), font);
        height = s.Height;
        box = new Rectangle(x, y, width, height);

        Pen pen = new Pen(Color.Black, 2);
        g.DrawString(sb.ToString(), font, Brushes.Blue, box);
        g.DrawRectangle(pen, box);
        pen.Dispose();
    }
}

关于c# - 如何确定将在矩形中绘制的文本的高度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41818496/

相关文章:

c# - 运行时如何填写构造函数参数?

c# - 如何在控制台应用程序中引用 Windows 8 运行时(特别是 BLE API)?

c# - ScrollableControl 滚动条始终归零

C# 结合 GDI+ 和 OpenGL/DirectX

c# - 从 System.Drawing.Image 在文件系统上创建一个新图像?

c# - 为什么即使使用 Monitor 时,并非所有成员变量都需要 volatile 以保证线程安全? (为什么这个模型真的有效?)

c# - 窗口显示红色 x,但我找不到错误通知

c# - 如何在 winforms 中第二次显示表单 "smoothly"?

.net - Winforms ComboBox SelectedValueChange 事件

c# - 使用 DrawString 将单个字符居中