Расширяемый WinForms TextBox - PullRequest
4 голосов
/ 30 июля 2009

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

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

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

Ответы [ 6 ]

7 голосов
/ 30 июля 2009

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

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

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

2 голосов
/ 08 августа 2011

Пост 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;
    }
}
2 голосов
/ 30 июля 2009

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

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();
    }
}
2 голосов
/ 30 июля 2009

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

private void HandleContentsResized(object sender, ContentsResizedEvenetArgs e)
{
    int newheight = e.NewRectangle.Height;
}
1 голос
/ 10 июня 2013

Я использую приведенный ниже код с успехом примерно до 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;
        }
    }
0 голосов
/ 30 июля 2009

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

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

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

...