RichEdit语法突出显示

时间:2014-03-01 02:57:59

标签: c++ windows winapi richedit

我需要你的帮助!所以,我正在使用语法高亮显示创建一个RichEdit,我这样做:

   SendMessage(hWin, WM_SETREDRAW, false, 0);
            CHARFORMAT2 format, old;
            format.cbSize = sizeof(format);
            old.cbSize = sizeof(format);
            MainRich.GetFormat(SCF_DEFAULT, &format);
            MainRich.GetFormat(SCF_DEFAULT, &old);
            format.dwMask = CFM_BOLD;       
            format.dwEffects = CFE_BOLD;
            CHARRANGE* c = MainRich.GetSelectionRange();
            int length = MainRich.GetLength();
            string str = string(MainRich.GetText());
            #define hl "true" //Example of syntax for highlight
            int last = 0;
            while (str.find(hl, last)!=string::npos)
            {
                MainRich.Select(str.find(hl, last), str.find(hl, last)+strlen(hl));
                MainRich.SetFormat(SCF_SELECTION, &format);
                last = str.find(hl, last)+strlen(hl);
            }
            MainRich.Select(c->cpMin, c->cpMax);
            MainRich.SetFormat(SCF_SELECTION, &old);
            SendMessage(hWin, WM_SETREDRAW, true, 0);
            UpdateWindow(hWin);
            }

但我发现在大文件中有很多突出显示它会变得迟钝,你有更好的方法吗?我检查了Iczelion's Assembly但是代码很乱,他似乎在画高亮在文本面前,但选择不起作用,对吧?如果确实如此,你能给我一些如何做到这一点的提示吗?谢谢!

3 个答案:

答案 0 :(得分:1)

我找到的最快的方法是构建原始RTF文档,然后通过EM_STREAMIN消息将其流式传输到控件。

EDITSTREAM stream;
stream.dwCookie = (DWORD_PTR)&streamData; // pointer your rtf data
stream.dwError = 0;
stream.pfnCallback = (EDITSTREAMCALLBACK)RtfStreamCallback; // callback which will push down the next chunk of rtf data when needed

LRESULT bytesAccepted = 0;
bytesAccepted = SendMessage(hWindow, EM_STREAMIN, SF_RTF, (LPARAM)&stream);

要记住的另一件事是您使用的RTF控件对性能有严重影响。当我这样做时,我发现默认控件(由Windows XP提供)非常慢,但Microsoft Office提供的RICHED20.DLL速度提高了几个数量级。您应该尝试可以访问的版本并进行一些性能比较。

链接到1.6 RTF Specification

答案 1 :(得分:1)

您对MainRich.GetText()的使用和std::string::find()的冗余调用是瓶颈。根本不检索文本。请改用CRichEditCtrl::FindText()

不要在最后恢复原始选择的原始格式。如果在应用突出显示之前选择了突出显示的关键字,该怎么办?你可以撤消它的突出显示。

您可以采取的另一项加速RichEdit的优化方法是在更改文本时使用CRichEditCtrl::SetEventMask()关闭事件(如EN_SELCHANGE),然后在完成后将其还原。

试试这个:

SendMessage(hWin, WM_SETREDRAW, false, 0);
CHARFORMAT2 format, old;
format.cbSize = sizeof(format);
MainRich.GetFormat(SCF_DEFAULT, &format);
old = format;
format.dwMask |= CFM_BOLD;       
format.dwEffects |= CFE_BOLD;
CHARRANGE* c = MainRich.GetSelectionRange();
DWORD mask = MainRich.GetEventMask();
MainRich.SetEventMask(0);
FINDTEXTEX ft;
ft.chrg.cpMin = 0;
ft.chrg.cpMax = MainRich.GetLength();
ft.lpstrText = "true";
while (MainRich.FindText(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD, &ft) != -1)
{
    MainRich.Select(ft.chrgText.cpMin, ft.chrgText.cpMax);
    MainRich.SetFormat(SCF_SELECTION, &format);
    ft.chrg.cpMin = ft.chrgText.cpMax;
}
MainRich.Select(ft.chrg.cpMax, ft.chrg.cpMax);
MainRich.SetFormat(SCF_SELECTION, &old);
MainRich.Select(c->cpMin, c->cpMax);
MainRich.SetEventMask(mask);
SendMessage(hWin, WM_SETREDRAW, true, 0);
UpdateWindow(hWin);

答案 2 :(得分:0)

最终的perf方法是在TextOut上进行API挂钩。

正确指定100%。

  • riched32.dll(richedit v1.0)从riched20.dll导入。

  • riched20.dll(richedit v2.0)使用: ExtTextOutA ExtTextOutW

  • msftedit.dll(richedit v4.1)使用: ExtTextOutA ExtTextOutW TextOutW