Comment faire défiler automatiquement vers le bas d'une boîte de texte multiligne?
j'ai une zone de texte avec la .Propriété multiligne définie à true. À intervalles réguliers, j'y ajoute de nouvelles lignes de texte. J'aimerais que la boîte de texte fasse défiler automatiquement la dernière entrée (la plus récente) chaque fois qu'une nouvelle ligne est ajoutée. Comment puis-je accomplir cela?
11 réponses
à intervalles réguliers, j'y ajoute de nouvelles lignes de texte. J'aimerais que la boîte de texte fasse défiler automatiquement la dernière entrée (la plus récente) chaque fois qu'une nouvelle ligne est ajoutée.
si vous utilisez TextBox.AppendText(string text)
, il défilera automatiquement jusqu'à la fin du texte nouvellement ajouté. Il évite le scintillement scrollbar si vous l'appelez dans une boucle.
il se trouve que c'est aussi un ordre de magnitude plus rapide que la concaténation sur la propriété .Text
. Bien que cela puisse dépendre de la fréquence à laquelle vous l'appelez; je testais avec une boucle serrée.
cette option ne fait pas défiler si elle est appelée avant que la zone de texte ne soit affichée, ou si la zone de texte n'est pas visible (par exemple dans un onglet différent d'un TabPanel). Voir L'Encadré .AppendText() pas le défilement automatique . Cela peut être ou ne pas être important, selon que vous require autoscroll quand l'utilisateur ne peut pas voir la boîte de texte.
il semble que la méthode alternative des autres réponses ne fonctionne pas non plus dans ce cas. Une façon de contourner cela est d'effectuer un défilement supplémentaire sur le VisibleChanged
événement:
textBox.VisibleChanged += (sender, e) =>
{
if (textBox.Visible)
{
textBox.SelectionStart = textBox.TextLength;
textBox.ScrollToCaret();
}
};
en Interne, AppendText
fait quelque chose comme ceci:
textBox.Select(textBox.TextLength + 1, 0);
textBox.SelectedText = textToAppend;
Mais il devrait y avoir aucune raison de le faire manuellement.
(si vous le décompilez vous-même, vous verrez qu'il utilise des méthodes internes peut-être plus efficaces, et a ce qui semble être un cas spécial mineur.)
vous pouvez utiliser l'extrait de code suivant:
myTextBox.SelectionStart = myTextBox.Text.Length;
myTextBox.ScrollToCaret();
qui se dérouleront automatiquement jusqu'à la fin.
il semble que l'interface ait changé en .NET 4.0. Il y a la méthode qui réalise tout ce qui précède. Comme Tommy Engebretsen l'a suggéré, le mettre dans un gestionnaire D'événements TextChanged le rend automatique.
textBox1.ScrollToEnd();
essayez d'ajouter le code suggéré à L'événement TextChanged:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
}
je devais ajouter un rafraîchissement:
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();
textBox1.Focus()
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
n'a pas fonctionné pour moi (Windows 8.1, quelle que soit la raison).
Et puisque je suis toujours sur .NET 2.0, Je ne peux pas utiliser ScrollToEnd.
Mais cela fonctionne:
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
j'ai trouvé une différence simple qui n'a pas été abordée dans ce fil.
si vous faites tous les appels ScrollToCarat()
dans le cadre de l'événement Load()
de votre formulaire, cela ne fonctionne pas. Je viens d'ajouter mon appel ScrollToCarat()
à l'événement Activated()
de mon formulaire, et ça marche très bien.
Modifier
il est important de ne faire ce défilement que la première fois que l'événement Activated
du formulaire est déclenché (pas sur les activations suivantes), ou il fera défiler chaque fois que votre forme est activée, ce qui est quelque chose que vous ne voulez probablement pas.
donc si vous ne faites que piéger l'événement Activated()
pour faire défiler votre texte lorsque votre programme se charge, alors vous pouvez simplement vous désabonner de l'événement à l'intérieur du gestionnaire d'événement lui-même, thusly:
Activated -= new System.EventHandler(this.Form1_Activated);
Si vous avez d'autres choses que vous devez faire à chaque fois que votre formulaire est activé, vous pouvez définir un bool
à true la première fois que votre événement Activated()
est déclenché, donc vous ne faites pas défiler sur les activations suivantes, mais vous pouvez toujours faire les autres choses que vous devez faire.
Aussi, si votre TextBox
est sur un onglet qui n'est pas le SelectedTab
, ScrollToCarat()
n'aura aucun effet. Donc, vous avez besoin au moins le faire l'onglet sélectionné pendant que vous faites défiler. Vous pouvez envelopper le code dans une paire YourTab.SuspendLayout();
et YourTab.ResumeLayout(false);
si votre forme clignote lorsque vous faites cela.
fin de l'édition
Espérons que cette aide!
cela fera défiler jusqu'à la fin de la zone de texte lorsque le texte est modifié, mais permet tout de même à l'utilisateur de faire défiler vers le haut
outbox.SelectionStart = outbox.Text.Length;
outbox.ScrollToEnd();
testé sur Visual Studio Enterprise 2017
pour quiconque atterrissant ici s'attendant à voir une implémentation de webforms, vous voulez utiliser le gestionnaire d'événements endRequest du Gestionnaire de requêtes de Page ( https://stackoverflow.com/a/1388170/1830512 ). Voici ce que j'ai fait pour ma boîte de texte dans une Page de contenu à partir d'une page maître, s'il vous plaît ignorer le fait que je n'ai pas utilisé une variable pour le contrôle:
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);
ça n'a marché que pour moi...
txtSerialLogging->Texte = "";
txtSerialLogging- > AppendText (s);
j'ai essayé tous les cas ci-dessus, mais le problème est dans mon cas des textes peuvent diminuer, augmenter et peuvent également rester statique pendant une longue période. statique signifie , statique longueur(lignes), mais le contenu est différent.
donc, je faisais face à une situation de saut de ligne à la fin quand la longueur (les lignes) reste le même pour quelques temps...
j'utilise une fonction pour cela:
private void Log (string s) {
TB1.AppendText(Environment.NewLine + s);
TB1.ScrollToCaret();
}