1

i need your help! So, i'm creating a RichEdit with syntax highlighter, i'm doing this way:

   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);
            }

But i see that in big files with a lot of highlight it gets laggy, do you have a better way of doing that?I checked Iczelion's Assembly but that code is a mess, he seems to be painting the highlight in front of the text but that way the selection doesn't work, right?If it does, can you give me some hints of how to do that?Thanks!

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219

3 Answers3

1

The fastest way I found was to build up the raw RTF document and then stream it to the control via the EM_STREAMIN message.

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);

Another thing to keep in mind is that the RTF control you use has serious implications on the performance. When I did this, I found that the default control (provided by Windows XP) was horribly slow, but the RICHED20.DLL provided by Microsoft Office was orders of magnitude faster. You should try out the versions that you have access to and do some performance comparisons.

Link to the 1.6 RTF Specification

josh poley
  • 7,236
  • 1
  • 25
  • 25
1

Your use of MainRich.GetText() and redundant calls to std::string::find() are bottlenecks. Don't retrieve the text at all. Use CRichEditCtrl::FindText() instead.

Don't restore the original format of the original selection at the end. What if a highlighted keyword were selected before you applied your highlighting? You would undo the highlighting for it.

Another optimization you can do to speed up the RichEdit is to use CRichEditCtrl::SetEventMask() to turn off events (like EN_SELCHANGE) while making changes to the text, and then restore them when finished.

Try this:

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);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

The ultimate perf approach is to do API hooking on TextOut.

To specify 100% correctly.

  • riched32.dll (richedit v1.0) imports from riched20.dll.

  • riched20.dll (richedit v2.0) uses: ExtTextOutA and ExtTextOutW

  • msftedit.dll (richedit v4.1) uses: ExtTextOutA, ExtTextOutW and TextOutW

JonPall
  • 814
  • 4
  • 9