简体   繁体   中英

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?

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 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.

你能将Text存储到一个字符串中,对字符串进行操作吗?在方法的最后,将它存储回Text属性中?

I would suggest looking at LockWindowUpdate


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

Try this out:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM