RichTextBox语法实时突出显示 – 禁用重绘

我正在创建一个带有RichTextBox的函数,并且可以访问关键字列表和’badwords’。 我需要突出显示我在用户输入时在RichTextBox中找到的任何关键字和坏词,这意味着每次发布编辑键时都会调用该函数。

我写过这个函数,但是盒子里的文字和光标闪烁得太过舒服了。

我发现了一个解决方案 – 在我编辑和格式化文本时禁用RichTextBox重绘自身的能力。 但是,我知道这样做的唯一方法是覆盖“WndProc”函数并拦截(我将要收集的内容)重绘消息如下:

protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == 0x00f) { if (paint) base.WndProc(ref m); else m.Result = IntPtr.Zero; } else base.WndProc(ref m); } 

在我开始突出显示之前将布尔’paint’设置为false,在我完成时将其设置为true。 但正如我所说,我制作的函数必须采用RichTextBox; 我不能使用子类。

那么,有没有办法禁止从外部自动重新绘制RichTextBox?

这是RichTextBox类的疏忽。 其他控件(如ListBox)支持BeginUpdate和EndUpdate方法来抑制绘制。 这些方法生成WM_SETREDRAW消息。 RTB实际上支持此消息,但他们忘记添加方法。

只需自己添加它们。 Project + Add Class,粘贴下面显示的代码。 编译并将控件从工具箱顶部拖放到表单上。

 using System; using System.Windows.Forms; using System.Runtime.InteropServices; class MyRichTextBox : RichTextBox { public void BeginUpdate() { SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero); } public void EndUpdate() { SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); this.Invalidate(); } [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); private const int WM_SETREDRAW = 0x0b; } 

或者在更新文本之前/之后直接调用SendMessage。

我没有积累足够的数据来修改汉斯的建议。 所以我添加了这个答案 ,提到可能需要通过调用InvalidateRect来请求重新绘制。 一些开始/结束更新实现在更新锁的最终版本时自动执行此操作。 同样在.Net, Control中 。 可以调用Invalidate ()来调用本机InvalidateRect函数。

MSDN: 最后,应用程序可以调用InvalidateRect函数来重新绘制列表框。

见WM_SETREDRAW

完成您要做的事情的最佳选择是创建一个multithreading应用程序。 您将需要创建一个线程来检查列表中的文本。 该线程将它找到的任何实例放入队列中。 您还需要创建另一个执行单词实际突出显示的线程。 因为您需要使用BeginInvoke()和Invoke()来更新UI,所以您需要确保调整调用它的速率。 我每秒不超过20次。 为此,您可以使用以下代码:

 DateTime lastInvoke=DateTime.Now; if ((DateTime.Now - lastInvoke).TotalMilliseconds >=42) { lastInvoke=DateTime.Now; ...Do your highlighting here... } 

此线程将检查您的队列中是否需要突出显示或重新突出显示的单词,并将不断检查队列中是否有任何新更新。 希望这是有道理的!