Rich text can be managed and output as a "text block" in a similar manner to plain text blocks. Use an TRTFBlock for this purpose, rather than the TTextBlock used for plain text and demonstrated in the previous tutorial.

Generally, the same methods, properties and principles apply to both block types. However, as text justification and font style are encoded in the RTF, the TRTFBlock does not have the (plain text) Justify and TextStyle properties as such. Also, varying font sizes may be specified in the RTF, so the height of each line may be different. To return the height of a given line, the following method can be used instead:

function RTFLineHeight(LineNumber: Integer): Double;

VPE can use default (but customisable) font and colour tables, and is very error tolerant with RTF coding... which makes it very easy to use "partial RTF coding" to format output. See the following example.

Example A: RTF On-the-Fly

A block of wrapping RTF can be output by creating and using a TRTFBlock on-the-fly. A TRTFBlock can also be dropped on a form for repeated use. In addition, you can "casually" compile the RTF string to output using minimal RTF coding.

Consider the string "This rich text example underlines some bold text to demonstrate using RTF-on-the-fly". We can compile this text with simple RTF coding using some of the RTF utility functions in VPE+ like this:

MyRTFNote := RTFEnclose(

'This rich text example underlines some ' +
RTFStyle('bold text', tsBU) +
' to demonstrate using ' +
RTFStyle('RTF-on-the-fly', tsI) + '.');


a) The RTF string is enclosed in an RTF control grouping using RTFEnclose. ie "{/rtf ...}"

b) The text style is set for two segments of text using the RTFStyle function.

So, given MyRTFNote, it could be printed like this:

The Code The Output

YPos := 20;
with TRTFBlock.Create(ReportWriter) do


OpenBlock(MyRTFNote, 30, 75, 0, 0);





a) The text starts at a vertical position of 20mm by setting the YPos property.

b) When opening the text block, the left boundary is initialised to 30mm and the right to 75mm.

These boundaries can also be set using the BlockLeft and BlockRight properties of TRTFBlock.

c) When opening the text block, the left and right text margins are both set to 0mm.

These margins can also be set using the TextLeftMargin and TextRightMargin properties of TRTFBlock.

d) PrintLines simply prints all lines in this case, but it can also facilitate incremental line output (by line count).

Alternatively, incremental output by height can be achieved using the PrintHeight method.

procedure PrintLines(

LineCountLimit: Integer = 0)

procedure PrintHeight(

HeightLimit: Double;
HeightMode: THeightMode = hmStopBefore);

Example B: Page Wrapping With an RTFBlock

Wrapping text with a TRTFBlock is very similar to wrapping text with a TTextBlock (you can apply similar methods and functions). However, a key difference is that RTF line heights can vary due to changes in font size within the block. Generally, this means that you need to test vertical space requirements based on height methods rather than on line count methods (which assume all lines have the same height depending on the active font).

Again, there are a variety of ways to control the output of an RTFBlock across a page break. This example prints the RTF string MyRTFNote from Example A line-by-line, starting a new page if the next line will not fit.

with TRTFBlock.Create(ReportWriter) do


OpenBlock(MyRTFNote, 30, 60, 0, 0);
while not IsFinished do

if not EnoughBandHeight(RTFLineHeight(1)) then







Note in particular that the function EnoughBandHeight always tests the RTFLineHeight of line number #1. This is because the line number passed to RTFLineHeight is always the nth line remaining - lines already printed are not counted unless you call ResetBlock to re-initialise the block output.

An alternative strategy would be to print what you can on the current page, and then start a new page if there is some remaining text to print:

if not IsFinished then