开发者

How to find runs of bold text inside of a RichEdit control?

开发者 https://www.devze.com 2023-03-01 06:13 出处:网络
I can obviously do it one character at a time using EM_GETCHARFORMAT, but it is extremely slow. One idea is to somehow use the ITextDocument/ITextFont interfaces, the other is to use the EM_STREAMOUT

I can obviously do it one character at a time using EM_GETCHARFORMAT, but it is extremely slow.

One idea is to somehow use the ITextDocument/ITextFont interfaces, the other is to use the EM_STREAMOUT message and manually parse the RTF. But I can't decide which approach is better and am very fuzzy on the implementation details. Wil开发者_如何学Pythonl appreciate any help, thanks!


I've found a solution that satisfies me and think will share it with you:

The ITextRange interface contains a very useful method Expand which can be used to find continuous runs of constant character (tomCharFormat) and paragraph (tomParaFormat) formatting.

Here is some sample code (warning: code is a proof-of-concept spaghetti without any error handling, apply refactoring as needed):

    // Get necessary interfaces
    IRichEditOle* ole;
    SendMessage(hwndRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&ole);

    ITextDocument* doc;
    ole->QueryInterface(__uuidof(ITextDocument), (void**)&doc);

    long start = 0;

    // Get total length:        
    ITextRange* range;
    doc->Range(start, start, &range);
    range->Expand(tomStory, NULL);
    long eof;
    range->GetEnd(&eof);

    // Extract formatting:

    struct TextCharFormat { long start, length; DWORD effects; }
    std::vector<TextCharFormat> fs;

    while(start < eof - 1)
    {
        doc->Range(start, start, &range);

        long n;
        range->Expand(tomCharFormat, &n); // <-- Magic happens here

        ITextFont* font;
        range->GetFont(&font);

        DWORD effects = 0;
        long flag;

        font->GetBold(&flag);
        if (flag == tomTrue) effects |= CFE_BOLD;

        font->GetItalic(&flag);
        if (flag == tomTrue) effects |= CFE_ITALIC;

        font->GetUnderline(&flag);
        if (flag == tomSingle) effects |= CFE_UNDERLINE;

        font->GetStrikeThrough(&flag);
        if (flag == tomTrue) effects |= CFE_STRIKEOUT;

        if (effects)
        {
            TextCharFormat f = { start, n, effects };
            fs.push_back(f);
        }
        start += n;
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消