Как найти прогоны жирного текста внутри элемента управления RichEdit? - PullRequest
0 голосов
/ 29 апреля 2011

Я, очевидно, могу сделать это по одному символу за раз, используя EM_GETCHARFORMAT, но это очень медленно.

Одна идея - как-то использовать интерфейсы ITextDocument / ITextFont, другая - использовать сообщение EM_STREAMOUT и вручнуюразбирать RTF.Но я не могу решить, какой подход лучше, и очень неясен в деталях реализации.Буду признателен за любую помощь, спасибо!

1 Ответ

2 голосов
/ 03 мая 2011

Я нашел решение, которое меня устраивает, и думаю, что поделится им с вами:

Интерфейс 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;
    }
...