For one of my projects, I needed to display some rich text in a Windows environment and in a browser and wanted them to appear roughly the same. I did not need to embed images or hyper-links, only some simple text formatting like the colour, the font name and the bold/italic/underline attributes. I also wanted to be able to control the background appearance. Using a HTML or a Rich Text control was therefore not an obvious option.
My intent was not to re-invent the wheel and provide a real HTML parser, simply a reduced HTML viewer that I could use almost anywhere. Feel free to improve the code and add support to other HTML tags (or your own if needed). Keep me posted of any improvements you make so I can upgrade the source (oh and my project).
I was then informed that Hans Dietrich had done a very similar development here. Looking at his control and inspired by a few of the comments posted there, I decided to create another control
CHTMLStatic that would support hyperlinks and the
Now comes the condescending section! Anyway, here is the list of tags supported by the
</STRONG>: sets the text between the tags in bold
</EM>: sets the text in italic
</U>: underlines the text
</FONT>: sets the font name, size and colour (the attributes supported are
SIZE). You can specify a colour by its rgb values or by its name (entering the list was rather painful)
<BR>: adds a line break
<P>: Defines a paragraph. The only supported attribute is
ALIGN (values can be left, center or right).
<CENTER>: Defines a centered paragraph.
<A HREF=url>: Defines an hyperlink.
Two main points are not in compliance with HTML:
- When 2 spaces are encountered, HTML assumes there is only one. I don't.
- The new line character is interpreted as a space in HTML, not here.
These would be easy to implement if you need them.
Using the Code
You can either use the code with
CHTMLDrawer and its
DrawText. This would only render the HTML and not allow you to use the hyperlinks.
void CHTMLDrawer::DrawText(CDC * pDC, const CString & strText,
const CHTMLFont & fntDefault,CRect & rctPosition,short nAlignment)
Alternatively, you could use the control
CHTMLStatic. You can define its background colour, the default font used, the color of a highlighted hyperlink and if it is underlined when highlighted.
CHTMLFont encapsulates the definition of a font (name, attributes, size and colour). You will need it to define the default font used.
CHTMLAtom is used as a temporary storage class and you will probably not need to refer to it in your code.
How it is done:
- Try to break the text into smaller parts that would have the same font settings. This is what I call an atom. This is done in
- Then whenever an atom overruns the right side of the rectangle, it is broken into smaller atoms (trying to break it where there are spaces). This function also computes the positions of atoms for their display. Check
BreakIntoLines() for details.
We also keep track of the atoms linked to a URL.
- Finally, we find the position of the lowest atom to centre the text vertically and apply the alignments in
- The actual drawing is done in
The whole thing is not too complicated, although I am pretty sure there are still a few bugs left and much room for optimization. Feel free to use it as much as you want as long you do not make me responsible for undesirable side effects!
Portions of the code were inspired (or copied) from Hans Dietrich who himself borrowed from Chris Maunder who himself is an avid reader of Paul DiLascia's MSJ column.
- 23/3/2003: v1.0
- 11/4/2003: v1.1
- Added the control
CHTMLStatic which supports hyperlinks (and the text stays nicely in the boundaries - thanks Doc McClenny).
- Added support of the following tags:
<A HREF=url> and
Text of different font sizes is correctly aligned and removed the 7 upperbound for a font size (thanks to Chopper for his comment).
- And finally, thanks to Hockey for showing me Hans Dietrich's article that I have shamelessly looted...
- 4/8/2003: v1.2
- I have a corrected a few bugs on
CHTMLStatic, the control encapsulating the drawer - resize problems and flickering of the cursor (thanks to Pranavamhari's remark)
- I have also added a new sample encapsulating the drawer into a view which allows a vertical scroll bar (this was Koh Zi Chun's idea... thanks for the positive feedback!)