¿Cómo agregar texto a RichTextBox sin desplazarse y perder la selección?

Necesito anexar texto a RichTextBox, y necesito realizarlo sin hacer que el cuadro de texto se desplace o pierda la selección de texto actual, ¿es posible?

El RichTextBox en WinForms es bastante shiny cuando juegas con el texto y los métodos de texto de selección.

Tengo un reemplazo estándar para apagar la pintura y desplazarse con el siguiente código:

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

y luego desde mi forma, puedo felizmente tener un control richtextbox libre de parpadeos:

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

Eche un vistazo a Prevenir AutoScrolling en C # RichTextBox

basado en el artículo LarsTech aquí algo agradable:

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

puedes usarlo así:

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

Esta solución es casi perfecta, excepto que no maneja correctamente las selecciones inversas (donde el símbolo de intercalación está al inicio de la selección, no al final, por ejemplo, MAYÚS + IZQUIERDA o se usa el mouse hacia arriba para seleccionar el texto).

Aquí hay una versión mejorada, con las siguientes características adicionales:

  • Si el símbolo de intercalación está al final del texto, permanece allí, desplazándose si es necesario.
  • Si la selección original comenzó o finalizó en el último carácter, cualquier texto adjunto se incluye en la nueva selección.

Esto significa que puede colocar el símbolo de intercalación al final del texto y controlar el texto que se agrega (monitoreo de archivos de registro de pensamientos). También significa que puede hacer CTRL + A para seleccionar todo, y tener cualquier texto adjunto incluido automáticamente en su selección.

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

Esto debería hacer lo que quieras:

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