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

7
我有一个文本框,可以返回不同长度的字符串,范围从5个字符到1000个字符不等。 它具有以下属性:
  • multiline = true(多行)
  • wordwrap = true(自动换行)
为了实现以下目标,我需要设置文本框的哪些其他属性?
  • 文本框的宽度应该固定
  • 文本框的高度根据返回的文本自动调整,例如,如果文本跨越3行,则将其调整为3行高。

2
我没有看到任何“?”。你的问题是什么?请不要写“我该如何做到这一点”。 - L.B
7个回答

11
尝试以下代码:

请尝试以下代码:

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;
     }
} 

如果文本框使用自定义字体,请使用 textBox1.Height = (textBox1.Font.Height + 2) * numberOfLines; - George
1
我是否应该使用不同于文本框的控件?有没有任何控件在其属性中内置了此功能? - whytheq
3
numberOfLines = textbox1.lines.count(); - bh_earth0

3

TextBox类似乎没有内置此功能的任何功能,但Font类具有Height属性,该属性返回基线之间的像素数。

还可以找出TextBox中文本占用的行数,如this博客文章所述(警告:不是非常优雅)。

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


3

我不敢相信还没有真正优雅的方法。这是我想出来的:

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

这是通过确定文本中最后一个字符的像素坐标来实现的。
您可以在设置内容后执行此操作,即在FormTextBox控件的OnLoadOnTextChanged中执行。如果用户调整窗体大小时固定宽度发生变化,则还应该注意这一点,即OnResizeOnClientSizeChangedTextBox支持AutoSize属性。但是,默认情况下已将其设置为true,并且在属性编辑器或IntelliSense中不显示。它仅用于字体高度更改,并且在使用MultiLine = true时不起作用:( - 在documentation中没有提到。
其他选项可能包括使用不同的控件,如RichTextBoxLabel。我还没有尝试过,但似乎Label更好地支持AutoSize

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

现在高度自动调整后,表单的锚定似乎不起作用了:文本框有时比表单更大,因此我无法看到文本框的底部。有什么想法吗? - whytheq

1
在TextBox上添加MaxHeight属性,如下所示。

1

您需要从代码中调整文本框的高度。计算行数(这篇文章可以帮助您完成此操作),然后将Textbox.Height设置为所需值(行数* 8px或更多,具体取决于TextBox内使用的字体)。

在链接的文章中,解决方案是重写TextBox控件类以能够获取行数;可能有其他方法来获取行数,但我认为文章中提出的解决方案非常优雅。


0

类似这样的代码可以获取文本框中实际绘制出来的文本高度:

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

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

现在有了MessageSize.Height,您就知道文本框中文本的高度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接