Huy*_*yen 17 c# wpf winapi textbox winforms
我有一个带有垂直滚动条的多行TextBox,它可以记录实时进程中的数据.目前,无论何时添加新行textBox.AppendText(),TextBox都会滚动到底部,以便您可以看到最后一个条目,这很棒.但是我有一个复选框来决定何时允许TextBox自动滚动.反正有没有这样做?
注意:
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.
}
}
Run Code Online (Sandbox Code Playgroud)
更新1:正如saggio建议的那样,我也认为这个问题的解决方案是确定当前文本中第一个字符在TextBox中显示的位置,然后再附加文本并在之后恢复它.但是怎么做呢?我试着像这样记录当前的光标位置,但它没有帮助:
int selpoint = txtLog.SelectionStart;
txtLog.AppendText(Environment.NewLine);
txtLog.AppendText(text);
txtLog.SelectionStart = selpoint;
Run Code Online (Sandbox Code Playgroud)
更新2 (问题已解决):我找到了一个可以在Stack Overflow上解决我的问题的解决方案.我已经优化了他们的代码以适应我的问题,如下所示:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
其他方式:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我为那些有类似问题的人发布了这些解决方案.感谢cgyDeveloper的源代码.
有没有人有更简单的方法?
这似乎很直接,但我可能会遗漏一些东西.如果Autochecked为true,则使用追加文本滚动到该位置,如果您不想滚动,只需添加文本.
更新......我错过了什么.您想要设置选择点,然后滚动到插入符号.见下文.
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
{
int caretPos = txtLog.Text.Length;
txtLog.Text += Environment.NewLine + text;
txtLog.Select(caretPos, 0);
txtLog.ScrollToLine(txtLog.GetLineIndexFromCharacterIndex(caretPos));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8887 次 |
| 最近记录: |