明らかに、EM_GETCHARFORMAT を使用して一度に 1 文字ずつ実行できますが、非常に遅いです。
1 つのアイデアは、ITextDocument/ITextFont インターフェイスを使用することです。もう 1 つは、EM_STREAMOUT メッセージを使用して手動で RTF を解析することです。しかし、どちらのアプローチが優れているかを判断することはできず、実装の詳細については非常に曖昧です。どんな助けにも感謝します、ありがとう!
私は私を満足させ、あなたとそれを共有すると思う解決策を見つけました:
このITextRangeインターフェースには、一定の文字( )および段落( )のフォーマットExpandの連続実行を見つけるために使用できる非常に便利なメソッドが含まれています。tomCharFormattomParaFormat
サンプルコードを次に示します(警告:コードはエラー処理のない概念実証スパゲッティです。必要に応じてリファクタリングを適用してください)。
// 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;
}