c# - como - ¿Cómo me desplazo automáticamente a la parte inferior de un cuadro de texto multilínea?
como programar un scrollbar en c# (11)
Tengo un cuadro de texto con la propiedad .Multiline establecida en true. A intervalos regulares, le estoy agregando nuevas líneas de texto. Me gustaría que el cuadro de texto se desplace automáticamente a la entrada más baja (la más reciente) cada vez que se agregue una nueva línea. ¿Cómo logro esto?
A intervalos regulares, le estoy agregando nuevas líneas de texto. Me gustaría que el cuadro de texto se desplace automáticamente a la entrada más baja (la más reciente) cada vez que se agregue una nueva línea.
Si usa TextBox.AppendText(string text)
, se desplazará automáticamente al final del texto recién agregado. Evita la barra de desplazamiento parpadeante si la llamas en un bucle.
También sucede que es un orden de magnitud más rápido que la concatenación en la propiedad .Text
. Aunque eso podría depender de la frecuencia con la que lo llames; Estaba probando con un lazo cerrado.
Esto no se desplazará si se llama antes de que se muestre el cuadro de texto, o si el cuadro de texto no está visible (por ejemplo, en una pestaña diferente de un panel de pestañas). Ver TextBox.AppendText () no desplazamiento automático . Esto puede o no ser importante, dependiendo de si requiere que se desplace automáticamente cuando el usuario no puede ver el cuadro de texto.
Parece que el método alternativo de las otras respuestas tampoco funciona en este caso. Una forma de VisibleChanged
es realizar un desplazamiento adicional en el evento VisibleChanged
:
textBox.VisibleChanged += (sender, e) =>
{
if (textBox.Visible)
{
textBox.SelectionStart = textBox.TextLength;
textBox.ScrollToCaret();
}
};
Internamente, AppendText
hace algo como esto:
textBox.Select(textBox.TextLength + 1, 0);
textBox.SelectedText = textToAppend;
Pero no debería haber ninguna razón para hacerlo manualmente.
(Si lo descompila usted mismo, verá que utiliza algunos métodos internos posiblemente más eficientes y que tiene lo que parece ser un caso especial menor).
Esto se desplazará hasta el final del cuadro de texto cuando se cambia el texto, pero aún así le permite al usuario desplazarse hacia arriba
outbox.SelectionStart = outbox.Text.Length;
outbox.ScrollToEnd();
probado en Visual Studio Enterprise 2017
Esto solo me funcionó ...
txtSerialLogging-> Text = "";
txtSerialLogging-> AppendText (s);
Probé todos los casos anteriores, pero el problema es que en mi caso los textos pueden disminuir, aumentar y también pueden permanecer estáticos durante mucho tiempo. Medios estáticos, longitud estática (líneas) pero el contenido es diferente.
Entonces, me enfrenté a una situación de salto de línea al final cuando la longitud (líneas) permanece igual por algunas veces ...
He encontrado una diferencia simple que no se ha abordado en este hilo.
Si está haciendo todas las llamadas ScrollToCarat()
como parte del evento Load()
de su formulario, no funciona. Acabo de agregar mi llamada ScrollToCarat()
al evento Activated()
mi formulario, y funciona bien.
Editar
Es importante realizar este desplazamiento solo la primera vez que se Activated
evento Activated
del formulario (no en activaciones posteriores), o se desplazará cada vez que se active su formulario, lo cual es algo que probablemente no desee.
Entonces, si solo está atrapando el evento Activated()
para desplazar el texto cuando se carga su programa, entonces simplemente puede cancelar la suscripción al evento dentro del controlador de eventos en sí:
Activated -= new System.EventHandler(this.Form1_Activated);
Si tiene otras cosas que debe hacer cada vez que se active su formulario, puede configurar un bool
como verdadero la primera vez que se Activated()
su evento Activated()
, por lo que no se desplaza en las activaciones posteriores, pero aún puede hacer lo otro. cosas que necesitas hacer
Además, si su TextBox
está en una pestaña que no es la ficha SelectedTab
, ScrollToCarat()
no tendrá ningún efecto. Así que necesitas al menos convertirla en la pestaña seleccionada mientras estás desplazando. Puede envolver el código en un YourTab.SuspendLayout();
y YourTab.ResumeLayout(false);
empareja si su forma parpadea cuando haces esto.
Fin de edición
¡Espero que esto ayude!
Intente agregar el código sugerido al evento TextChanged:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
}
Necesitaba agregar una actualización:
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();
Para cualquier persona que aterrice aquí esperando ver una implementación de formularios web, desea utilizar el controlador de eventos endRequest del Administrador de solicitudes de página ( https://.com/a/1388170/1830512 ). Esto es lo que hice para mi TextBox en una página de contenido de una página maestra, ignore el hecho de que no usé una variable para el control:
var prm = Sys.WebForms.PageRequestManager.getInstance();
function EndRequestHandler() {
if ($get(''<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>'') != null) {
$get(''<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>'').scrollTop =
$get(''<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>'').scrollHeight;
}
}
prm.add_endRequest(EndRequestHandler);
Puedes usar el siguiente fragmento de código:
myTextBox.SelectionStart = myTextBox.Text.Length;
myTextBox.ScrollToCaret();
que se desplazará automáticamente hasta el final.
Yo uso una función para esto:
private void Log (string s) {
TB1.AppendText(Environment.NewLine + s);
TB1.ScrollToCaret();
}
textBox1.Focus()
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
No funcionó para mí (Windows 8.1, cualquiera que sea la razón).
Y como todavía estoy en .NET 2.0, no puedo usar ScrollToEnd.
Pero esto funciona:
public class Utils
{
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int SendMessage(System.IntPtr hWnd, int wMsg, System.IntPtr wParam, System.IntPtr lParam);
private const int WM_VSCROLL = 0x115;
private const int SB_BOTTOM = 7;
/// <summary>
/// Scrolls the vertical scroll bar of a multi-line text box to the bottom.
/// </summary>
/// <param name="tb">The text box to scroll</param>
public static void ScrollToBottom(System.Windows.Forms.TextBox tb)
{
if(System.Environment.OSVersion.Platform != System.PlatformID.Unix)
SendMessage(tb.Handle, WM_VSCROLL, new System.IntPtr(SB_BOTTOM), System.IntPtr.Zero);
}
}
VB.NET:
Public Class Utils
<System.Runtime.InteropServices.DllImport("user32.dll", CharSet := System.Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function SendMessage(hWnd As System.IntPtr, wMsg As Integer, wParam As System.IntPtr, lParam As System.IntPtr) As Integer
End Function
Private Const WM_VSCROLL As Integer = &H115
Private Const SB_BOTTOM As Integer = 7
'''''' <summary>
'''''' Scrolls the vertical scroll bar of a multi-line text box to the bottom.
'''''' </summary>
'''''' <param name="tb">The text box to scroll</param>
Public Shared Sub ScrollToBottom(tb As System.Windows.Forms.TextBox)
If System.Environment.OSVersion.Platform <> System.PlatformID.Unix Then
SendMessage(tb.Handle, WM_VSCROLL, New System.IntPtr(SB_BOTTOM), System.IntPtr.Zero)
End If
End Sub
End Class