2012-04-16 62 views
6

在我的WinForm应用程序中,我有一个多行TextBox控件(uiResults),用于在处理大量项目时报告进度。使用AppendText非常适合在每次更新时自动滚动到底部,但如果用户滚动回来读取一些较旧的数据,我需要关闭自动滚动。如果可能,我宁愿远离P/Invoke调用。在添加行时维护TextBox滚动位置

是否有可能检测用户是否回滚而不使用P/Invoke?现在,我只检查SelectionStart其工作,但需要用户插入符号从文本框的端移动停止自动滚屏:

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

我的主要问题是使用Text属性追加一个字符串时,该文本框被滚动到开始。我试图通过存储插入位置并在更新后重置并滚动来解决这个问题,但是这会导致当前行移动到底部(当然,因为ScrollToCaret滚动的距离不超过必要的距离以将脱字符视为视图)。

[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(); 
} 

回答

2

Auto-scrolling text box uses more memory than expected

在问题的代码实现正是你所期待的。文本被添加,但滚动只发生在滚动条位于最底部时。

+0

当垂直滚动条移动并且不通过AppendText触发WM_VSCROLL时触发。是否有不同的信息要捕捉? – 2012-04-16 16:48:06

+0

@Brad Rem。没有理解你的完整问题。更新。 – 2012-04-16 19:49:26

0

您是否接受另一种方法,因为您一定会以这种方式陷入困境,解决方案将会变得复杂(您想要避免的纠结等等)。例如。假设你找到一种方法来“检测用户是否回滚”,并停止滚动到底部。但阅读完该行后,用户可能希望滚动到底部功能恢复。那么为什么不给用户一种控制自动滚动的方法。这是我会怎么做呢?

使用一个RichTextBox显示的数据和一个复选框来控制自动滚动,那么你的代码可能是这样的:

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

RichTextBox的默认情况下不会自动滚动到底部AppendText,所以第一行将始终可见(而不是新添加的行)。但是,如果用户选中了名为AutoScroll的复选框,我们的代码会将richtextbox滚动到显示新行的底部。如果用户想要手动滚动读取一行,他首先需要取消选中该复选框。

+1

不幸的是,当使用AppendText时,它似乎也是'RichTextBox'滚动到底部 - 但只有当控件具有焦点时。但由于用户有时需要选择并复制文本,因此这种方法可能无法正常工作。 – Anlo 2012-04-19 18:04:31