Pregunta

He creado un cuadro de texto en una aplicación de Windows Forms que comienza a una altura para ingresar texto en una sola línea. Pero me gustaría que el cuadro de texto aumente automáticamente su altura si el usuario ingresa el texto que está dentro del control.

Actualmente, para este cuadro de texto, tengo las propiedades multiline y wordwrap establecidas en true. He intentado usar el evento TextChanged para determinar cuándo se ha envuelto el texto pero no puedo encontrar ninguna propiedad que me ayude con esto. La propiedad Líneas no proporciona ninguna ayuda con el texto envuelto; solo para el texto que el usuario haya pulsado enter para comenzar una nueva línea.

¿Cómo puedo hacer que mi cuadro de texto expanda su altura cada vez que el texto se ajusta más allá del ancho del cuadro de texto?

¿Fue útil?

Solución

El mismo tipo de idea que otros han publicado, ponga esto en su evento TextChanged:

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

Necesitarás algún tipo de altura mínima, y ??posiblemente para especificar algún relleno, pero esto funciona.

Otros consejos

Si está dispuesto a usar un RichTextBox en su lugar (que, en mi experiencia, es un tipo de control gruñón que viene con muchas peculiaridades), puede usar el evento ContentsResized, que le brinda el nuevo tamaño requerido:

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

Acabo de escribir esto para un control de etiqueta para un proyecto diferente. Conseguí el código del proyecto de código en algún lugar, creo. Cambiarlo a un cuadro de texto debería ser tan simple como cambiar 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();
    }
}

La publicación de AdamSane fue útil, pero el cuadro de texto no creció. Me gustaría hacer algunas modificaciones. Mis mods están abajo:

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

Estoy usando el código de abajo con éxito hasta aproximadamente la décima línea, luego quita 1 carácter, pero esto funciona para mí. No me preguntes sobre los números aleatorios como - 7 y - 12, tienen algo que ver con el relleno

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

Lamentablemente, no puedo proporcionar detalles pero probablemente necesitarás hacer una implementación personalizada.

Derivaría un nuevo tipo de cuadro de texto, ExpandableTextBox, y luego necesitarás implementarlo a mano.

Esto también parece relevante para lo que está buscando: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/11dfb280-b113-4ddf-ad59-788f78d2995a

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top