Introduction
Manipulating Rich Text (rtf) - how to ?
I expected it to be a relatively easy task. Surely there was something out there that would allow rtf generation. I did not want to resort to html. I required tables, colour, font size, image insertion and ability to merge rtf documents preserving all the above formatting. I really needed something simple and fast. Say, as simple and easy as StringBuilder
.
Rich Text is ubiquitous in windows forms applications yet notoriously hard to manipulate programatically. Display of Rich Text is based on the RTF specification (an archaic format dating way back to early windows 3). Parsing Rich Text is beyond the scope of this article. If however you need to build up simple rich text with FontStyle, Font ,Font size Font Colour, Back Colour ,Tables , insert images and merge RTF documents then this little utility class (RTFBuilder
) may help you.
Background
Programatic manipulation of rtf within a RichTextBox was my first attempt and I had it working to a point. The crunch came when trying to create tables. Anyone who has worked with the RichTextBox and rtf tables will know what I mean.
After searching all over the net - Nada, apart from commercial controls. I was prepared to pay a couple of hundred dollars for such a utility, if it existed.
TextControl [Very good commercial control] allows display , editing and programatic generation of rtf but was out of my price range and requirements. I also didnt like the size of the redistributable(s) and the dificulties of distributing the control with a small clickonce application for example. The required learning curve for programtic generation of rtf using the TextControls API was not insignificant.
RtfBuilder
was the fruition of many hours learning RTF specification and tinkering.
RtfBuilder
is based on the StringBuilder
Class Design.
The beauty of RtfBuilder
is in the fact that it can be used interchangeably in place of StringBuilder. It will output RTF when ToString() is Called.
You can rapidly develop your code initially with StringBuilder and convert to usage of Rich Text by replacing the initiallisation code with that of a RtfBuilder
.
The RTF Specification is reasonably large and this utility uses just a small part of the specification to get the job done. Because of its(and my) limited knowledge of the RTF specification there are limitations when merging RTF documents. Generally , RTF code from RRichTextBox Controls can be merged but Rich Text pasted from MS Word may cause problems when merging.
There are ways around prickly specifications when you just want to perfom a subset of functions to get the job done.
Using the code
Create a new RTFBuilder and simply append text in a similar fashion to StringBuilder
usage.
Add Formatting Calls where necessary prior to appending text. The format resets to default after each append unless enclosed within a using FormatLock(sb.FormatLock()) {sb.Append....}
RtfBuilder
also allows AppendFormat("{0}" ,arg); etc
plus AppendLineFormat("{0}",arg); (something that StringBuilder
should Have!)
RTFBuilderbase sb = new RTFBuilder();
sb.AppendLine("AppendLine Basic Text");
sb.Append("append text1").Append("append text2").Append("append text3").Append("append text4").AppendLine();
sb.FStyle(FontStyle.Bold).AppendLine("Bold");
sb.FStyle(FontStyle.Italic).AppendLine("Italic");
sb.FStyle(FontStyle.Strikeout).AppendLine("Strikeout");
sb.FStyle(FontStyle.Underline).AppendLine("Underline");
sb.FStyle(FontStyle.Bold | FontStyle.Italic | FontStyle.Strikeout | FontStyle.Underline).AppendLine("Underline/Bold/Italic/Underline");
sb.ForeColor(KnownColor.Red).AppendLine("ForeColor Red");
sb.BackColor(KnownColor.Yellow).AppendLine("BackColor Yellow");
string rtf = sb.ToString();
this.richTextBox1.Rtf = rtf.
sb.AppendRTFDocument(this.richTextBox4.Rtf);
sb.InsertImage(image);
I have included a very simple application demonstrating usage.

Also included is a GDFBuilder class which can be used interchangeably with the RtfBuilder(base) in code and will generate Images that can be displayed in a paging image control(included.)
I have used the GDFBuilder to create RTF popup tooltips and RTF Labels by painting the images from the GDFPages exposed by the GDFPageManager. You will need to hunt around in the code to find this feature. I have not included a demo - if you are interested post a comment.
Points of Interest
It would be very easy to add a HtmlBuilder using the existing RtfBuilder framework.
Extensive usage of IDisposable within the code that inserts RTF format commands. This allows rtf codes such as that for bold (/b) to be prepended before a string insert and that for unbold (/b0) to be appended after the string insert.
Table creation is nonintuitive. You need to Create the Row and Cell Definitions then enumerate over the cells. The EnumerateCells functions returns an IEnumerable<RTFBuilderbase> which represents the underlying RTFBuilderbase wrapped with a class that emits the correct RTF row and cell codes as you enumerate the cells.
private void AddRow1(RTFBuilderbase sb, params string[] cellContents)
{
Padding p = new Padding { All = 50 };
RTFRowDefinition rd = new RTFRowDefinition(88, RTFAlignment.TopLeft, RTFBorderSide.Default, 15, SystemColors.WindowText, p);
RTFCellDefinition[] cds = new RTFCellDefinition[cellContents.Length];
for (int i = 0; i < cellContents.Length; i++)
{
cds[i] = new RTFCellDefinition(88 / cellContents.Length, RTFAlignment.TopLeft, RTFBorderSide.Default, 15, Color.Blue, Padding.Empty);
}
int pos = 0;
foreach (RTFBuilderbase item in sb.EnumerateCells(rd, cds))
{
item.ForeColor(KnownColor.Blue).FStyle(FontStyle.Bold | FontStyle.Underline);
item.BackColor(Color.Yellow);
item.Append(cellContents[pos++]);
}
}
History
Version 1
I have used this code extensively for the last few months in an application and it seems stable but the GDFBuilder still needs work.
Also Padding and Borders for table/row/cells is incomplete and nonfunctional.