I have a RichTextBox where I need to update the Text property frequently, but when I do so the RichTextBox \"blinks\" annoyingly as it refreshes all throughout a method call
Here is complete and working example:
private const int WM_USER = 0x0400;
private const int EM_SETEVENTMASK = (WM_USER + 69);
private const int WM_SETREDRAW = 0x0b;
private IntPtr OldEventMask;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
public void BeginUpdate()
{
SendMessage(this.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
OldEventMask = (IntPtr)SendMessage(this.Handle, EM_SETEVENTMASK, IntPtr.Zero, IntPtr.Zero);
}
public void EndUpdate()
{
SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
SendMessage(this.Handle, EM_SETEVENTMASK, IntPtr.Zero, OldEventMask);
}
I would suggest looking at LockWindowUpdate
[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
Could you just store the Text into a string, do your manipulations on the string, and at the end of the method, store it back into the Text property?
Try this out:
myRichTextBox.SuspendLayout();
DoStuff();
myRichTextBox.ResumeLayout();
I asked the original question, and the answer that worked best for me was BoltBait's use of SendMessage() with WM_SETREDRAW. It seems to have fewer side effects than the use of the WndProc method, and in my application performs twice as fast as LockWindowUpdate.
Within my extended RichTextBox class, I just added these two methods, and I call them whenever I need to stop restart repainting while I'm doing some processing. If I were wanting to do this from outside of the RichTextBox class, I think it would work by just replacing "this" with the reference to your RichTextBox instance.
private void StopRepaint()
{
// Stop redrawing:
SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
// Stop sending of events:
eventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero);
}
private void StartRepaint()
{
// turn on events
SendMessage(this.Handle, EM_SETEVENTMASK, 0, eventMask);
// turn on redrawing
SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
// this forces a repaint, which for some reason is necessary in some cases.
this.Invalidate();
}
Found here: http://bytes.com/forum/thread276845.html
I ended up sending a WM_SETREDRAW via SendMessage to disable then reenable followed by an Invalidate() after I finished updating. That seemed to work.
I've never tried this method. I have written an application with a RTB that has syntax highlighting and used the following in the RTB class:
protected override void WndProc(ref Message m)
{
if (m.Msg == paint)
{
if (!highlighting)
{
base.WndProc(ref m); // if we decided to paint this control, just call the RichTextBox WndProc
}
else
{
m.Result = IntPtr.Zero; // not painting, must set this to IntPtr.Zero if not painting otherwise serious problems.
}
}
else
{
base.WndProc(ref m); // message other than paint, just do what you normally do.
}
}
Hope this helps.