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

时间:2010-07-19 15:19:24

标签: c# graphics richtextbox syntax-highlighting

我正在创建一个带有RichTextBox的函数,并且可以访问关键字列表& '脏话'。我需要突出显示任何关键字&我在RichTextBox 中找到的badwords,当用户键入时,这意味着每次释放编辑键时都会调用该函数。

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

我发现了一个解决方案 - 在我编辑和格式化文本时禁用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?'

3 个答案:

答案 0 :(得分:23)

这是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。

答案 1 :(得分:5)

我没有积累足够的数据来修改汉斯的建议。所以我添加了答案来提及可能需要通过调用 InvalidateRect 来请求重新绘制。一些Begin / End Update实现在最终发布更新锁时自动执行此操作。类似地,在.Net中,控制无效()可以调用它来调用本机 InvalidateRect 函数。

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

请参阅WM_SETREDRAW

答案 2 :(得分:0)

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

DateTime lastInvoke=DateTime.Now;

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

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