Вопрос

Я создал текстовое поле в приложении Windows Forms, которое начинается с высоты для ввода текста в одну строку. Но я бы хотел, чтобы текстовое поле автоматически увеличивало свою высоту, если пользователь вводит текст, заключенный в элемент управления.

В настоящее время для этого текстового поля свойства multiline и wordwrap установлены в true. Я пытался использовать событие TextChanged, чтобы определить, когда текст был перенесен, но я не могу найти какое-либо свойство, которое поможет мне в этом. Свойство Lines не предоставляет никакой помощи с переносимым текстом; только для текста, который пользователь нажал ввод, чтобы начать новую строку.

Как я могу заставить мое текстовое поле увеличивать свою высоту каждый раз, когда текст обходит ширину текстового поля?

Это было полезно?

Решение

Идея такого же рода, как и другие, добавьте ее в событие textChanged:

Dim s As SizeF = TextRenderer.MeasureText(txt.Text, txt.Font, txt.ClientRectangle.Size, TextFormatFlags.WordBreak)
txt.Height = CInt(s.Height)

Вам понадобится какая-то минимальная высота и, возможно, для указания отступов, но это работает.

Другие советы

Если вы хотите вместо этого использовать RichTextBox (который, по моему опыту, является своего рода сварливым элементом управления, который сопровождается множеством измышлений), вы можете использовать событие ContentsResized, которое дает новый требуемый размер:

private void HandleContentsResized(object sender, ContentsResizedEvenetArgs e)
{
    int newheight = e.NewRectangle.Height;
}

Я только что написал это для элемента управления меткой для другого проекта. Я получил код от проекта кода где-то, я думаю. Изменить его на текстовое поле должно быть так же просто, как сменить базу.

public class GrowLabel : Label
{
    private bool _growing;
    //public bool GrowFontSize { get; set; }

    public GrowLabel()
    {
        AutoSize = false;
        //GrowFontSize = false;
    }

    public override sealed bool AutoSize
    {
        get { return base.AutoSize; }
        set { base.AutoSize = value; }
    }

    private void ResizeLabel()
    {
        if (_growing) return;
        try
        {
            _growing = true;

            var sz = new Size(Width, Int32.MaxValue);
            sz = TextRenderer.MeasureText(Text, Font, sz, TextFormatFlags.WordBreak);
            Height = sz.Height;
        }
        finally
        {
            _growing = false;
        }
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        ResizeLabel();
    }

    protected override void OnFontChanged(EventArgs e)
    {
        base.OnFontChanged(e);
        ResizeLabel();
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        ResizeLabel();
    }
}

Сообщение AdamSane было полезным, но текстовое поле не увеличилось. Я бы сделал некоторые изменения. Мои моды ниже:

class GrowTextBox : TextBox
{
    private double m_growIndex = 0.0;
    private Timer m_timer;

    public GrowTextBox()
    {
        AutoSize = false;
        this.Height = 20;

        // Without the timer, I got a lot of AccessViolationException in the System.Windows.Forms.dll.
        m_timer = new Timer();
        m_timer.Interval = 1;
        m_timer.Enabled = false;
        m_timer.Tick += new EventHandler(m_timer_Tick);

        this.KeyDown += new KeyEventHandler(GrowTextBox_KeyDown);
    }

    void GrowTextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
        {
            this.SelectAll();
        }
    }

    void m_timer_Tick(object sender, EventArgs e)
    {
        var sz = new Size(Width, Int32.MaxValue);
        sz = TextRenderer.MeasureText(Text, Font, sz, TextFormatFlags.TextBoxControl);

        m_growIndex = (double)(sz.Width / (double)Width);

        if (m_growIndex > 0)
            Multiline = true;
        else
            Multiline = false;

        int tempHeight = (int)(20 * m_growIndex);

        if (tempHeight <= 20)
            Height = 20;
        else
            Height = tempHeight;

        m_timer.Enabled = false;
    }

    public override sealed bool AutoSize
    {
        get { return base.AutoSize; }
        set { base.AutoSize = value; }
    }


    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        m_timer.Enabled = true;
    }

    protected override void OnFontChanged(EventArgs e)
    {
        base.OnFontChanged(e);
        m_timer.Enabled = true;
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        m_timer.Enabled = true;
    }
}

Я использую приведенный ниже код с успехом примерно до 10-й строки, затем он получает 1 символ, но это работает для меня. Не спрашивайте меня о случайных числах, таких как - 7 и - 12, они имеют какое-то отношение к заполнению

    private void txbDescription_TextChanged(object sender, EventArgs e)
    {
        SizeF s = TextRenderer.MeasureText(txbDescription.Text, txbDescription.Font, txbDescription.ClientRectangle.Size, TextFormatFlags.TextBoxControl);

        int lines = (int)Math.Ceiling((decimal)Convert.ToInt32(s.Width - 7) / ((decimal)txbDescription.Width - 12));

        if (lines == 0)
        {
            txbDescription.Height = 20;
        }
        else
        {
            txbDescription.Height = 20 + (lines - 1) * 13;
        }
    }

К сожалению, я не могу предоставить подробности, но вам, вероятно, понадобится выполнить пользовательскую реализацию.

Я бы получил новый тип текстового поля - ExpandableTextBox - и затем вам нужно будет реализовать его вручную.

Это также относится к тому, что вы ищете: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/11dfb280-b113-4ddf-ad59-788f78d2995a

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top