如何在RichEdit控件中查找粗体文本的运行?

时间:2011-04-29 05:13:21

标签: c++ winapi text rtf richedit

显然我可以使用EM_GETCHARFORMAT一次一个字符,但它非常慢。

一个想法是以某种方式使用ITextDocument / ITextFont接口,另一个是使用EM_STREAMOUT消息并手动解析RTF。但是我无法确定哪种方法更好,而且在实现细节方面非常模糊。非常感谢任何帮助,谢谢!

1 个答案:

答案 0 :(得分:2)

我找到了一个满足我的解决方案,并认为会与您分享:

ITextRange接口包含一个非常有用的方法Expand,可用于查找常量字符(tomCharFormat)和段落(tomParaFormat)格式的连续运行。 / p>

以下是一些示例代码(警告:代码是一个概念验证意大利面,没有任何错误处理, 根据需要进行重构):

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