Prevent Autoscrolling in RichTextBox
我有一个使用RichTextBox控件实现的只读数据记录窗口。 我希望能够禁用用户单击控件时发生的自动滚动,以便用户可以为复制/粘贴操作或其他操作选择特定的日志。 但是,一旦用户单击RichTextBox,它就会自动滚动到底部,这很困难。
有人知道一种替代此行为的方法吗?
谢谢!
如果未隐藏选择,则RichTextBox控件会自动滚动到当前选择。 RichTextBox.AppendText()除了附加文本外,还修改当前选择,因此间接触发"自动滚动"行为。请注意,如果RichTextBox.HideSelection设置为true,则当控件未处于焦点时,该选择将被隐藏;这说明了您描述的行为,其中仅当用户单击控件时才发生自动滚动。 (从而给予重点关注)
为防止这种情况,在添加文本时需要执行以下操作:
您可能还需要检查所选内容是否已经在文本末尾,如果允许,则允许自动滚动行为-这实际上是在模仿Visual Studio的"输出"窗口的行为。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | [System.Runtime.InteropServices.DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam); const int WM_USER = 0x400; const int EM_HIDESELECTION = WM_USER + 63; void OnAppend(string text) { bool focused = richTextBox1.Focused; //backup initial selection int selection = richTextBox1.SelectionStart; int length = richTextBox1.SelectionLength; //allow autoscroll if selection is at end of text bool autoscroll = (selection==richTextBox1.Text.Length); if (!autoscroll) { //shift focus from RichTextBox to some other control if (focused) textBox1.Focus(); //hide selection SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 1, 0); } richTextBox1.AppendText(text); if (!autoscroll) { //restore initial selection richTextBox1.SelectionStart = selection; richTextBox1.SelectionLength = length; //unhide selection SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 0, 0); //restore focus to RichTextBox if(focused) richTextBox1.Focus(); } } |
您可以看一下执行以下操作:
1 2 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr LockWindowUpdate(IntPtr Handle); |
然后在附加日志数据的方法中(我在这里做一些假设),您可能会执行以下操作:
1 2 3 4 5 6 7 | LockWindowUpdate(this.Handle); int pos = richTextBox1.SelectionStart; int len = richTextBox1.SelectionLength; richTextBox1.AppendText(yourText); richTextBox1.SelectionStart = pos; richTextBox1.SelectionLength = len; LockWindowUpdate(IntPtr.Zero); |
我用计时器做了一个小测试应用程序,该计时器在richtextbox上执行了追加操作,并停止了滚动,因此可以选择文本。它存在一些位置问题,并不完美,但是也许可以帮助您找到自己的解决方案。
祝一切顺利!
SytS的解决方案存在一个问题,当"附加"某些文本时,滚动条将移动,从而使所选内容移至面板顶部。
一个解决方案是使用以下命令保存/恢复滚动位置:
1 2 3 4 5 | [System.Runtime.InteropServices.DllImport("User32.dll")] extern static int GetScrollPos(IntPtr hWnd, int nBar); [System.Runtime.InteropServices.DllImport("user32.dll")] static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw); |
这个解决方案对我来说比较完整。