多行文本框根据文本量自动调整高度

我有一个文本框,可以返回各种字符串,长度从5个字符到1000个字符不等。 它具有以下属性:

  • multiline = true
  • wordwrap = true

我需要设置哪些文本框的其他属性才能使以下内容成为可能?

  • 盒子的宽度应该是固定的
  • 框的高度根据文本返回的数量自动调整,例如,如果文本在3行上运行,则调整为3行高。

请尝试以下代码:

 public partial class Form1 : Form { private const int EM_GETLINECOUNT = 0xba; [DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int SendMessage(int hwnd, int wMsg, int wParam, int lParam); public Form1() { InitializeComponent(); } private void textBox1_TextChanged(object sender, EventArgs e) { var numberOfLines = SendMessage(textBox1.Handle.ToInt32(), EM_GETLINECOUNT, 0, 0); this.textBox1.Height = (textBox1.Font.Height + 2) * numberOfLines; } } 

似乎没有任何function可以在TextBox类中内置它,但Font类有一个Height属性,它返回基线之间的像素数。

也可以找出TextBox中文本占用的行数,如本博客文章中所述(警告:它并不完全优雅)。

一旦获得此信息,您应该能够使用一些简单的数学使TextChanged处理程序相应地设置TextBox的高度。

您需要从代码中调整文本框的高度。 计算行数( 这篇文章可以帮助你解决这个问题 ),然后将Textbox.Height设置为你需要的值(行数* 8px左右,具体取决于TextBox使用的字体) 。

在链接文章解决方案是覆盖TextBox控件类,以便能够获得行数; 可能还有其他方法可以获得行数,但文章中建议的解决方案看起来非常优雅。

 private void tb_TextChanged(object sender, EventArgs e) { tb.Height = (tb.Text.Split('\n').Length + 2 ) * tb.Font.Height; } 

这样的东西给出了文本的高度,就像在文本框中绘制它一样:

 SizeF MessageSize = MyTextBoxControl.CreateGraphics() .MeasureString(MyTextBoxControl.Text, MyTextBoxControl.Font, MyTextBoxControl.Width, new StringFormat(0)); 

我不确定StringFormat应该是什么,但StringFormatFlags值似乎不适用于默认的TextBox组合。

现在使用MessageSize.Height您可以知道文本框中文本的高度。

我无法相信仍然没有真正优雅的方式。 这是我困惑的事情:

 textBox.Height += textBox.GetPositionFromCharIndex(textBox.Text.Length - 1).Y + 3 + textBox.Font.Height - textBox.ClientSize.Height; 

这通过确定文本的最后一个字符的像素坐标来工作。

您可以在设置内容后执行此操作,即在Form OnLoadTextBox控件的OnTextChanged中执行此操作。 如果在用户调整表单大小时固定宽度发生变化,您还应该注意这一点,即OnResizeOnClientSizeChanged

TextBox支持AutoSize属性。 但是,默认情况下它已设置为true ,并且未在属性编辑器或IntelliSense中显示。 它仅用于字体高度更改,并且在使用MultiLine = true时不起作用:( – 文档中未提及此内容 。

其他选项可能包括使用不同的控件,如RichTextBoxLabel 。 我还没试过,但似乎Label更好地支持AutoSize 。