如何在 RichEdit 控件内查找粗体文本?

发布于 2024-11-03 17:06:17 字数 170 浏览 6 评论 0原文

显然,我可以使用 EM_GETCHARFORMAT 一次处理一个字符,但速度非常慢。

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

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. Will appreciate any help, thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你的笑 2024-11-10 17:06:17

我找到了一个令我满意的解决方案,并希望与您分享:

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

这是一些示例代码(警告:代码是概念验证意大利面条,没有任何错误处理,
根据需要应用重构):

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

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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文