John
John

Reputation:

How do you prevent a RichTextBox from refreshing its display?

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.

I was hoping to find an easy way to temporarily suppress the screen refresh until my method is done, but the only thing I've found on the web is to override the WndProc method. I've employed this approach, but with some difficulty and side effects, and it makes debugging harder, too. It just seems like there's got to be a better way of doing this. Can someone point me to a better solution?

Upvotes: 11

Views: 11146

Answers (6)

JohnnyM
JohnnyM

Reputation: 29536

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.

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

    private const int WM_SETREDRAW = 0xB;
    const int WM_USER = 0x400;
    const int EM_GETEVENTMASK = WM_USER + 59;
    const int EM_SETEVENTMASK = WM_USER + 69;

    private IntPtr eventMask;

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

Upvotes: 11

puch4tek
puch4tek

Reputation: 171

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

Upvotes: 17

Curious Developer
Curious Developer

Reputation:

I would suggest looking at LockWindowUpdate


[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]

Upvotes: -1

BoltBait
BoltBait

Reputation: 11489

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.

Upvotes: 4

Howler
Howler

Reputation: 2252

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?

Upvotes: 0

BKimmel
BKimmel

Reputation: 611

Try this out:

myRichTextBox.SuspendLayout();
DoStuff();
myRichTextBox.ResumeLayout();

Upvotes: -4

Related Questions