2009-07-30 11 views
4

J'ai créé une zone de texte dans une application Windows Forms qui commence à une hauteur permettant de saisir du texte sur une seule ligne. Mais je voudrais que la zone de texte augmente automatiquement sa hauteur si l'utilisateur entre le texte qui est enveloppé dans le contrôle.Extension WinForms TextBox

Actuellement, pour cette zone de texte, j'ai les propriétés multiline et wordwrap définies sur true. J'ai essayé d'utiliser l'événement TextChanged pour déterminer quand le texte a été enveloppé mais je suis incapable de trouver n'importe quelle propriété qui m'aidera avec ceci. La propriété Lines ne fournit aucune aide avec le texte enveloppé; uniquement pour le texte que l'utilisateur a appuyé sur Entrée pour commencer une nouvelle ligne.

Comment puis-je agrandir ma zone de texte à chaque fois que le texte dépasse la largeur de la zone de texte?

Répondre

7

même genre d'idée que d'autres ont posté, mis dans votre événement TextChanged:

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

Vous aurez besoin d'une sorte de hauteur minimale, et peut-être de préciser certains types de remplissage, mais cela fonctionne .

+0

Grande réponse et je vais l'utiliser dans mon projet. Merci! –

+0

+1 pour TextRenderer.MeasureText –

2

Si vous êtes prêt à utiliser un RichTextBox à la place (qui, dans mon expérience, est une sorte de contrôle grincheux qui vient avec beaucoup de bizarreries) , vous pouvez utiliser l'événement ContentsResized, ce qui vous donne la nouvelle taille requise:

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

Cela a fonctionné pour moi –

2

Je viens d'écrire ceci pour un contrôle d'étiquette pour un autre projet. J'ai trouvé le code du projet de code quelque part je pense. Le changer en une boîte de texte devrait être aussi simple que de changer la base.

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

Merci, AdamSane, ce fut une très bonne réponse aussi. J'ai trouvé Andy plus simple et je l'ai utilisé à la place. –

2

La publication d'AdamSane a été utile, mais la zone de texte n'a pas évolué. Je voudrais faire quelques modifications. Mes mods sont ci-dessous:

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

J'utilise le code ci-dessous avec succès jusqu'à la 10e ligne au sujet, il obtient 1 caractère hors tension, mais cela fonctionne pour moi. Ne me demandez pas sur les nombres aléatoires comme - 7 et - 12, ils ont quelque chose à voir avec un rembourrage

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