Hello Bruce,
I think MoveToNextParagraph() or MoveToNextRun() always set current caret to the beginning of paragraph or run, but MoveToNextCharacter() can make current caret at the end of text block. To verify this, please test the following code:
CaretPtr pCaret = textBlock->CreateStartCaret(); while (!pCaret->IsAtEnd()) pCaret->MoveToNextCharacter(); WPrintfString wStr(L"Is Caret at the end = %d", pCaret->IsAtEnd()); mdlDialog_dmsgsPrint(wStr.GetWCharCP());