2009-07-30 5 views
4

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

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

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

ответ

7

такая же идея, как другие выложили, это в вашем случае TextChanged:

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

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

+0

Отличный ответ, и я буду использовать его в своем проекте. Благодаря! –

+0

+1 для TextRenderer.MeasureText –

0

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

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

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

2

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

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

Это работало для меня –

2

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

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(); 
    } 
} 
+0

Спасибо, AdamSane, это был действительно хороший ответ тоже. Я нашел Энди проще и использовал его. –

2

Сообщение 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; 
    } 
} 
1

Я буду использовать этот код с успехом примерно до 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; 
     } 
    }