RichEdit语法突出显示

问题描述 投票:1回答:3

我需要你的帮助!所以,我正在创建一个带语法高亮显示的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但是代码是一团糟,他似乎在文本前面画了亮点但是选择不起作用的方式,对吧?如果确实如此,你能给我一些如何做到这一点的提示吗?谢谢!

c++ windows winapi richedit
3个回答
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
投票

你使用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);

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
© www.soinside.com 2019 - 2024. All rights reserved.