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.
我有一个RichTextBox,我需要经常更新Text属性,但是当我这样做时,RichTextBox会因为在整个方法调用中刷新所有内容而“眨眼”。
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?
我希望找到一种简单的方法来暂时禁止屏幕刷新,直到我的方法完成,但我在网上找到的唯一的事情就是覆盖WndProc方法。我采用了这种方法,但有一些困难和副作用,它也使调试更加困难。看起来似乎必须有更好的方法来做到这一点。有人能指出我更好的解决方案吗?
6 个解决方案
#1
11
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);
}
#2
9
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.
我问了原来的问题,最适合我的答案是BoltBait使用带有WM_SETREDRAW的SendMessage()。它似乎比使用WndProc方法的副作用更少,并且在我的应用程序中执行的速度是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.
在我扩展的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
3
Found here: http://bytes.com/forum/thread276845.html
在此处找到: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.
我最后通过SendMessage发送WM_SETREDRAW来禁用然后重新启用,然后在完成更新后使用Invalidate()。这似乎有效。
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:
我从未尝试过这种方法。我编写了一个带有语法高亮的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.
}
}
Hope this helps.
希望这可以帮助。
#4
0
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?
你能将Text存储到一个字符串中,对字符串进行操作吗?在方法的最后,将它存储回Text属性中?
#5
-1
I would suggest looking at LockWindowUpdate
我建议看一下LockWindowUpdate
[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
#6
-3
Try this out:
试试这个:
myRichTextBox.SuspendLayout();
DoStuff();
myRichTextBox.ResumeLayout();
#1
11
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);
}
#2
9
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.
我问了原来的问题,最适合我的答案是BoltBait使用带有WM_SETREDRAW的SendMessage()。它似乎比使用WndProc方法的副作用更少,并且在我的应用程序中执行的速度是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.
在我扩展的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
3
Found here: http://bytes.com/forum/thread276845.html
在此处找到: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.
我最后通过SendMessage发送WM_SETREDRAW来禁用然后重新启用,然后在完成更新后使用Invalidate()。这似乎有效。
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:
我从未尝试过这种方法。我编写了一个带有语法高亮的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.
}
}
Hope this helps.
希望这可以帮助。
#4
0
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?
你能将Text存储到一个字符串中,对字符串进行操作吗?在方法的最后,将它存储回Text属性中?
#5
-1
I would suggest looking at LockWindowUpdate
我建议看一下LockWindowUpdate
[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true,
ExactSpelling=true, CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
#6
-3
Try this out:
试试这个:
myRichTextBox.SuspendLayout();
DoStuff();
myRichTextBox.ResumeLayout();