2012-04-16 7 views
6

En mi aplicación WinForm tengo un control TextBox de líneas múltiples (uiResults) que se utiliza para informar el progreso mientras se procesa una gran cantidad de elementos. Usar AppendText funciona muy bien para desplazarse automáticamente hacia abajo en cada actualización, pero si el usuario se desplaza hacia atrás para leer algunos datos anteriores, necesito desactivar el desplazamiento automático. Preferiría mantenerme alejado de las llamadas de P/Invoke si es posible.Mantener la posición de desplazamiento de TextBox al agregar la línea

¿Es posible detectar si el usuario se ha desplazado hacia atrás sin utilizar P/Invoke? Por ahora, sólo echa un SelectionStart que funciona, pero requiere que el usuario mueva el cursor desde el final de la caja de texto para detener el desplazamiento automático:

if(uiResults.SelectionStart == uiResults.Text.Length) 
{ 
    uiResults.AppendText(result + Environment.NewLine); 
} 

Mi principal problema es que al anexar una cadena utilizando la propiedad Text, la El cuadro de texto se desplaza hacia el principio. Traté de resolver esto almacenando la posición de intercalación y reiniciando y desplazándome hacia ella después de la actualización, pero esto hace que la línea actual se mueva hacia abajo (por supuesto, ya que ScrollToCaret no desplaza más de la distancia necesaria para ver la interpolación)

[Continued from above] 
else 
{ 
    int pos = uiResults.SelectionStart; 
    int len = uiResults.SelectionLength; 
    uiResults.Text += result + Environment.NewLine; 
    uiResults.SelectionStart = pos; 
    uiResults.SelectionLength = len; 
    uiResults.ScrollToCaret(); 
} 

Respuesta

2

Auto-scrolling text box uses more memory than expected

El código en la pregunta implementa exactamente lo que busca. Se agrega texto, pero el desplazamiento solo ocurre si la barra de desplazamiento está en la parte inferior.

+0

WM_VSCROLL se activa cuando la barra de desplazamiento vertical se mueve y NO se dispara a través de AppendText. ¿Hay diferentes mensajes para atrapar? –

+0

@Brad Rem. No entendiste tu pregunta completa. Actualizado. –

0

¿Está abierto a otro enfoque, porque está obligado a meterse en problemas de esta manera y las soluciones se volverán complejas (pinvoke, etc. que desea evitar). Por ej. supongamos que encuentra una forma de "detectar si el usuario se ha desplazado hacia atrás" y deja de desplazarse hacia abajo. Pero después de leer la línea, el usuario puede querer que la función de desplazamiento hacia abajo se reanude. Entonces, ¿por qué no darle al usuario una forma de controlar el desplazamiento automático? Así es como yo lo haría ...

Utilice un RichTextBox para mostrar datos y una casilla de verificación para controlar el desplazamiento automático, a continuación, el código podría ser algo como esto:

 richTextBox1.AppendText(result + Environment.NewLine); 
     if (checkBoxAutoScroll.Checked) 
     { 
      richTextBox1.SelectionStart = richTextBox1.Text.Length; 
      richTextBox1.ScrollToCaret(); 
     } 

RichTextBox por defecto no se desplazará automáticamente a abajo en AppendText, por lo que la primera línea siempre estaría visible (y no la línea recién añadida). Pero si el usuario marca esta casilla llamada AutoScroll, nuestro código desplazará el richtextbox a la parte inferior donde se muestran las líneas nuevas. Si el usuario quiere desplazarse manualmente para leer una línea, primero deberá desmarcar la casilla de verificación.

+1

Desafortunadamente, parece que el 'RichTextBox' se desplaza hacia abajo cuando se usa' AppendText', pero solo cuando el control tiene foco. Pero dado que los usuarios a veces necesitan seleccionar y copiar texto, este enfoque lamentablemente no funcionará. – Anlo

Cuestiones relacionadas