Как предотвратить автоматическую прокрутку TextBox при добавлении текста?
У меня есть многострочный TextBox с вертикальной полосой прокрутки, которая записывает данные из процесса в реальном времени. В настоящее время всякий раз, когда новая строка добавляетсяtextBox.AppendText()
TextBox прокручивается вниз, так что вы можете увидеть последнюю запись, это здорово. Но у меня есть флажок, чтобы решить, когда TextBox разрешен для автоматической прокрутки. Есть какой-либо способ сделать это?
Примечание:
Я хочу использовать TextBox, потому что добавленный текст состоит из нескольких строк и форматируется пробелами, поэтому его непросто использовать с ListBox или ListView.Я пытался добавить новую строкуtextBox.Text += text
, но TextBox всегда прокручивается вверх.Если у нас есть решение для этого, то еще один вопрос - как предотвратить автоматическую прокрутку TextBox, когда пользователь использует полосу прокрутки для просмотра где-нибудь еще в TextBox, в то время как TextBox добавляет текст?
private void OnTextLog(string text)
{
if (chkAutoScroll.Checked)
{
// This always auto scrolls to the bottom.
txtLog.AppendText(Environment.NewLine);
txtLog.AppendText(text);
// This always auto scrolls to the top.
//txtLog.Text += Environment.NewLine + text;
}
else
{
// I want to append the text without scrolls right here.
}
}
Обновление 1: КакSaggio предполагает, я также думаю, что решение этой проблемы состоит в том, чтобы определить положение первого символа в текущем тексте, который отображается в TextBox, прежде чем добавлять текст и восстанавливать его после этого. Но как это сделать? Я попытался записать текущую позицию курсора, как это, но это не помогло:
int selpoint = txtLog.SelectionStart;
txtLog.AppendText(Environment.NewLine);
txtLog.AppendText(text);
txtLog.SelectionStart = selpoint;
Обновление 2 (проблема была решена): Я нашелрешение это может решить мою проблему здесь на переполнении стека. Я оптимизировал их код в соответствии с моей проблемой следующим образом:
// Constants for extern calls to various scrollbar functions
private const int SB_VERT = 0x1;
private const int WM_VSCROLL = 0x115;
private const int SB_THUMBPOSITION = 0x4;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
private static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);
private void AppendTextToTextBox(TextBox textbox, string text, bool autoscroll)
{
int savedVpos = GetScrollPos(textbox.Handle, SB_VERT);
textbox.AppendText(text + Environment.NewLine);
if (autoscroll)
{
int VSmin, VSmax;
GetScrollRange(textbox.Handle, SB_VERT, out VSmin, out VSmax);
int sbOffset = (int)((textbox.ClientSize.Height - SystemInformation.HorizontalScrollBarHeight) / (textbox.Font.Height));
savedVpos = VSmax - sbOffset;
}
SetScrollPos(textbox.Handle, SB_VERT, savedVpos, true);
PostMessageA(textbox.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * savedVpos, 0);
}
private void OnTextLog(string text)
{
AppendTextToTextBox(txtLog.Text, Environment.NewLine + text, chkAutoScroll.Checked);
}
По-другому:
private const int SB_VERT = 0x1;
private const int WM_VSCROLL = 0x115;
private const int SB_THUMBPOSITION = 0x4;
private const int SB_BOTTOM = 0x7;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
private static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam);
private void AppendTextToTextBox(TextBox textbox, string text, bool autoscroll)
{
int savedVpos = GetScrollPos(textbox.Handle, SB_VERT);
textbox.AppendText(text + Environment.NewLine);
if (autoscroll)
{
PostMessageA(textbox.Handle, WM_VSCROLL, SB_BOTTOM, 0);
}
else
{
SetScrollPos(textbox.Handle, SB_VERT, savedVpos, true);
PostMessageA(textbox.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * savedVpos, 0);
}
}
Я выкладываю эти решения для тех, у кого похожая проблема. Спасибо заcgyDeveloperисходный код
У кого-нибудь есть более простой способ?