如何在不滚动和丢失选择的情况下将文本附加到RichTextBox?

我需要将文本附加到RichTextBox,并且需要在不使文本框滚动或丢失当前文本选择的情况下执行它,是否可能?

当您使用文本和选择文本方法时,WinForms中的RichTextBox非常快乐。

我有一个标准的替代品,用以下代码关闭绘画和滚动:

class RichTextBoxEx: RichTextBox { [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam); [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, IntPtr lParam); const int WM_USER = 0x400; const int WM_SETREDRAW = 0x000B; const int EM_GETEVENTMASK = WM_USER + 59; const int EM_SETEVENTMASK = WM_USER + 69; const int EM_GETSCROLLPOS = WM_USER + 221; const int EM_SETSCROLLPOS = WM_USER + 222; Point _ScrollPoint; bool _Painting = true; IntPtr _EventMask; int _SuspendIndex = 0; int _SuspendLength = 0; public void SuspendPainting() { if (_Painting) { _SuspendIndex = this.SelectionStart; _SuspendLength = this.SelectionLength; SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref _ScrollPoint); SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); _EventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero); _Painting = false; } } public void ResumePainting() { if (!_Painting) { this.Select(_SuspendIndex, _SuspendLength); SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref _ScrollPoint); SendMessage(this.Handle, EM_SETEVENTMASK, 0, _EventMask); SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero); _Painting = true; this.Invalidate(); } } } 

然后从我的forms,我可以愉快地拥有一个无闪烁的richtextbox控件:

 richTextBoxEx1.SuspendPainting(); richTextBoxEx1.AppendText("Hey!"); richTextBoxEx1.ResumePainting(); 

根据LarsTech的文章,这里有一些不错的东西:

 using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Drawing; namespace yournamespace { class RichTextBoxEx : RichTextBox { [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam); [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, IntPtr lParam); const int WM_USER = 0x400; const int WM_SETREDRAW = 0x000B; const int EM_GETEVENTMASK = WM_USER + 59; const int EM_SETEVENTMASK = WM_USER + 69; const int EM_GETSCROLLPOS = WM_USER + 221; const int EM_SETSCROLLPOS = WM_USER + 222; Point _ScrollPoint; bool _Painting = true; IntPtr _EventMask; int _SuspendIndex = 0; int _SuspendLength = 0; public bool Autoscroll = true; public void SuspendPainting() { if (_Painting) { _SuspendIndex = this.SelectionStart; _SuspendLength = this.SelectionLength; SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref _ScrollPoint); SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); _EventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero); _Painting = false; } } public void ResumePainting() { if (!_Painting) { this.Select(_SuspendIndex, _SuspendLength); SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref _ScrollPoint); SendMessage(this.Handle, EM_SETEVENTMASK, 0, _EventMask); SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero); _Painting = true; this.Invalidate(); } } new public void AppendText(string text) // overwrites RichTextBox.AppendText { if (Autoscroll) base.AppendText(text); else { SuspendPainting(); base.AppendText(text); ResumePainting(); } } } } 

你可以像这样使用它:

 var textbox = new RichTextBoxEx(); textbox.Autoscroll = false; textbox.AppendText("Hi"); 

这个解决方案几乎可以点亮,除了它没有正确处理反向选择(其中插入符号位于选择的开头,而不是结尾 – 例如SHIFT + LEFT或向上鼠标拖动用于选择文本)。

这是一个改进版本,具有以下附加function:

  • 如果插入符号位于文本的末尾,则它将保留在那里,如果需要则滚动。
  • 如果原始选择在最后一个字符上开始或结束,则任何附加文本都包含在新选择中。

这意味着您可以将插入符号放在文本的末尾并监视要添加的文本(想想日志文件监视)。 这也意味着您可以执行CTRL + A选择全部,并在您的选择中自动包含任何附加文本。

 class RichTextBoxEx : RichTextBox { [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam); [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, IntPtr lParam); [DllImport("user32")] private static extern int GetCaretPos(out Point p); const int WM_USER = 0x400; const int WM_SETREDRAW = 0x000B; const int EM_GETEVENTMASK = WM_USER + 59; const int EM_SETEVENTMASK = WM_USER + 69; const int EM_GETSCROLLPOS = WM_USER + 221; const int EM_SETSCROLLPOS = WM_USER + 222; private Point oScrollPoint; private bool bPainting = true; private IntPtr oEventMask; private int iSuspendCaret; private int iSuspendIndex; private int iSuspendLength; private bool bWasAtEnd; public int CaretIndex { get { Point oCaret; GetCaretPos(out oCaret); return this.GetCharIndexFromPosition(oCaret); } } public void AppendTextWithoutScroll(string text) { this.SuspendPainting(); this.AppendText(text); this.ResumePainting(); } private void SuspendPainting() { if (this.bPainting) { this.iSuspendCaret = this.CaretIndex; this.iSuspendIndex = this.SelectionStart; this.iSuspendLength = this.SelectionLength; this.bWasAtEnd = this.iSuspendIndex + this.iSuspendLength == this.TextLength; SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref this.oScrollPoint); SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); this.oEventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero); this.bPainting = false; } } private void ResumePainting() { if (!this.bPainting) { if (this.iSuspendLength == 0) { if (!bWasAtEnd) { this.Select(this.iSuspendIndex, 0); } } else { // Original selection was to end of text if (bWasAtEnd) { // Maintain end of selection at end of new text this.iSuspendLength = this.TextLength - this.iSuspendIndex; } if (this.iSuspendCaret > this.iSuspendIndex) { // Forward select (caret is at end) this.Select(this.iSuspendIndex, this.iSuspendLength); } else { // Reverse select (caret is at start) this.Select(this.iSuspendIndex + this.iSuspendLength, -this.iSuspendLength); } } SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref this.oScrollPoint); SendMessage(this.Handle, EM_SETEVENTMASK, 0, this.oEventMask); SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero); this.bPainting = true; this.Invalidate(); } } } 

这应该做你想要的:

  Dim tempStart As Int32 Dim tempLength As Int32 tempStart = RichTextBox1.SelectionStart tempLength = RichTextBox1.SelectionLength RichTextBox1.Text += "dsfkljwerhsdlf" RichTextBox1.SelectionStart = tempStart RichTextBox1.SelectionLength = tempLength