Pregunta

Mi aplicación Windows Forms tiene un cuadro de texto que estoy usando como un archivo de registro. Estoy añadiendo texto sin forma parpadeante usando TextBox.AppendText(string);, sin embargo cuando intento de purgar viejo texto (como propiedad .Texto del control alcanza el límite .MaxLength), me sale horrible parpadeo.

El código que estoy usando es el siguiente:

public static void AddTextToConsoleThreadSafe(TextBox textBox, string text)
{
    if (textBox.InvokeRequired)
    {
        textBox.Invoke(new AddTextToConsoleThreadSafeDelegate(AddTextToConsoleThreadSafe), new object[] { textBox, text });
    }
    else
    {
        // Ensure that text is purged from the top of the textbox
        // if the amount of text in the box is approaching the
        // MaxLength property of the control

        if (textBox.Text.Length + text.Length > textBox.MaxLength)
        {
            int cr = textBox.Text.IndexOf("\r\n");
            if (cr > 0)
            {
                textBox.Select(0, cr + 1);
                textBox.SelectedText = string.Empty;
            }
            else
            {
                textBox.Select(0, text.Length);
            }
        }


        // Append the new text, move the caret to the end of the
        // text, and ensure the textbox is scrolled to the bottom

        textBox.AppendText(text);
        textBox.SelectionStart = textBox.Text.Length;
        textBox.ScrollToCaret();
    }
}

¿Hay una manera más ordenada de purgar las líneas de texto de la parte superior del control que no causa parpadeo? Un cuadro de texto no tiene el BeginUpdate () / EndUpdate () métodos que un ListView tiene.

Es un control TextBox incluso el control más adecuado para un registro de la consola?

Edit: El parpadeo TextBox parece ser el cuadro de texto desplazándose hacia arriba a la parte superior (mientras que purgar el texto en la parte superior del control), y luego inmediatamente se desplaza hacia abajo a la parte inferior. -. Todo sucede muy rápidamente, así que sólo ver el parpadeo repetido

esta pregunta , y la sugerencia fue utilizar un cuadro de lista, sin embargo, no sé si esto va a funcionar en mi situación, ya que (en la mayoría de los casos) que estoy recibiendo el texto para el cuadro de lista, un carácter a la vez.

¿Fue útil?

Solución

El problema es que está agregando (remoción) de un carácter a la vez repetida y rápidamente. Una solución sería la de amortiguar los personajes a medida que se añaden y actualizar el cuadro de texto a intervalos mayores (independientemente de la cantidad de caracteres), por ejemplo, cada 250 milisegundos.

Esto requeriría:

  • para tener una matriz o pila de caracteres en el que se añaden
  • para tener un temporizador que llamar a un delegado que en realidad hacer la actualización con los caracteres almacenados en la pila

Otra opción es utilizar ambas cada 250 ms y 100 caracteres, lo que suceda primero. Pero esto probablemente complicar el código sea más sin ningún beneficio tangible.

Otros consejos

Mathijs respuesta es que funciona para mí. He modificado ligeramente para que pueda usar con cualquier control - una extensión de control:

namespace System.Windows.Forms
{
    public static class ControlExtensions
    {
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool LockWindowUpdate(IntPtr hWndLock);

        public static void Suspend(this Control control)
        {
            LockWindowUpdate(control.Handle);
        }

        public static void Resume(this Control control)
        {
            LockWindowUpdate(IntPtr.Zero);
        }

    }
}

Así que todo lo que necesita hacer es:

myTextBox.Suspend();
// do something here.
myTextBox.Resume();

funciona bien. Todo el parpadeo paradas.

he encontrado una solución buscando en Internet:

    [System.Runtime.InteropServices.DllImport("user32.dll")]

    public static extern bool LockWindowUpdate(IntPtr hWndLock);

    internal void FillTB(TextBox tb, string mes) 
    {
       try
       {
          LockWindowUpdate(tb.Handle);

          // Do your thingies with TextBox tb
       }
       finally
       {
          LockWindowUpdate(IntPtr.Zero);
       }
    }

¿Ha establecido el búfer doble en su ventana principal?

este código en su constructor después de la llamada InitializeComponent se sumará el doble búfer y posiblemente reducir el parpadeo.

this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer,true);

¿Usted intentó SuspendLayout () / ResumeLayout () alrededor de todas sus operaciones de actualización?

También puede llamar Clear () en el cuadro de texto a continuación, volver a asignar el texto truncado.

Si su intento de aplicar algún tipo de visor de archivos de registro, se puede utilizar un cuadro de lista en su lugar.

Me parece que el uso SelectedText = Texto reducirá drásticamente el parpadeo. Para las actualizaciones muy rápidos, el parpadeo se localiza a sólo el nuevo texto y no obtendrá ningún comportamiento extraño de la barra de desplazamiento saltando.

void UpdateTextBox(string message)
{
   myTextBox.SelectionStart = myTextBox.Text.Length;
   myTextBox.SelectedText = message;
}

También puede usar esto para sobrescribir el texto escrito previamente - a medida que se necesita para la actualización de un contador o descargar porcentaje por ejemplo:

void UpdateTextBox(string message, int jumpBack)
{
   myTextBox.SelectionStart = Math.Max(myTextBox.Text.Length - jumpBack, 0);
   myTextBox.SelectionLength = jumpBack;
   myTextBox.SelectedText = message;
}

Aparte de eso, no parece haber ningún método simple para reducir el parpadeo en el cuadro de texto .NET.

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