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





Попробуйте это:
myRichTextBox.SuspendLayout();
DoStuff();
myRichTextBox.ResumeLayout();
SuspendLayout () здесь не помогает.
Не могли бы вы просто сохранить текст в строке, произвести манипуляции со строкой и в конце метода сохранить его обратно в свойство Text?
Найдено здесь: 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.
Никогда не пробовал этот метод. Я написал приложение с 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.
}
}
Надеюсь это поможет.
WM_SETREDRAW у меня работал. Должен быть таким же, как LockWindowUpdate.
Я бы посоветовал посмотреть LockWindowUpdate
[DllImport("user32.dll", EntryPoint = "LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
-1. Это неправильное использование. См. blogs.msdn.com/b/oldnewthing/archive/2007/02/19/1716211.aspx.
Я задал исходный вопрос, и ответ, который лучше всего сработал для меня, - это использование 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();
}
Есть ли шанс завершить код? Это не совсем компилируемо, как написано в настоящее время.
Ожидается вызов Invalidate (). Я использовал вариант этого в приложении MDI, где каждое из дочерних окон MDI содержало RichTextBox. В этом случае мне пришлось аннулировать управление с помощью child.richTextBox.Invalidate();.
Вот полный и рабочий пример:
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);
}
вам также может потребоваться добавить myRichTextBox.Enabled = false; а более поздний Enabled = true;