Как вы препятствуете обновлению RichTextBox своего дисплея? - PullRequest
8 голосов
/ 10 октября 2008

У меня есть RichTextBox, где мне нужно часто обновлять свойство Text, но когда я это делаю, RichTextBox раздражающе «мигает», так как обновляет все при вызове метода.

Я надеялся найти простой способ временно отключить обновление экрана, пока не завершится мой метод, но единственное, что я нашел в Интернете, - это переопределить метод WndProc. Я использовал этот подход, но с некоторыми сложностями и побочными эффектами, и это также затрудняет отладку. Просто кажется, что должен быть лучший способ сделать это. Может кто-нибудь указать мне на лучшее решение?

Ответы [ 6 ]

13 голосов
/ 28 сентября 2014

Вот полный и рабочий пример:

    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);
    }
9 голосов
/ 11 октября 2008

Я задал оригинальный вопрос, и лучшим ответом для меня было использование BoltBait SendMessage () с WM_SETREDRAW. Кажется, что у него меньше побочных эффектов, чем при использовании метода WndProc, и в моем приложении он работает вдвое быстрее, чем LockWindowUpdate.

В моем расширенном классе RichTextBox я просто добавил эти два метода и вызываю их всякий раз, когда мне нужно прекратить перерисовку заново, пока я выполняю некоторую обработку. Если бы я хотел сделать это извне класса RichTextBox, я думаю, что это сработало бы, просто заменив «this» ссылкой на ваш экземпляр RichTextBox.

    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();
    }
3 голосов
/ 10 октября 2008

Найдено здесь: http://bytes.com/forum/thread276845.html

В итоге я отправил WM_SETREDRAW через SendMessage, чтобы отключить и снова включить после Invalidate () после завершения обновления. Это, похоже, сработало.

Я никогда не пробовал этот метод. Я написал приложение с RTB, у которого есть подсветка синтаксиса и использовал следующее в классе RTB:

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

Надеюсь, это поможет.

0 голосов
/ 10 октября 2008

Я бы предложил посмотреть LockWindowUpdate


[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
0 голосов
/ 10 октября 2008

Не могли бы вы просто сохранить текст в строку, выполнить ваши манипуляции со строкой и в конце метода сохранить его обратно в свойство Text?

0 голосов
/ 10 октября 2008

Попробуйте это:

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