function is nearly a drop-in replacement of the standard
function, with limited support for HTML
formatting tags. It is only nearly a replacement
because a few formatting flags of the real
function are not supported. More limiting, perhaps, is
that only a minimal subset of HTML
tags is supported.
is inspired by Pocket HTML
by Petter Hesselberg; published in Windows Developer
Journal, February 2000. The implementation is fully
mine, however, because I felt that the HTML
parser in Pocket HTML
leaves to be desired. My implementation is very limited,
but already more complete than that of Pocket HTML;
it is more easily extensible; and it scales better by
allocating resources on an "as-needed" basis,
rather than grabbing all possibly needed
resources on start-up of the function.
when there are full HTML
parsers with comprehensive support for all tags? My
reasons for implementing this are:
- Windows API
functions do not support markup codes at all;
very limited markup support is already very helpful.
This is why Petter Hesselberg published Pocket HTML
(and my implementation improves on it).
consists of a single, and fairly small, file (less
than 400 lines). It is therefore fairly easy to add
it to a project. No extra components or DLLs are
needed for the application, because
can easily be statically linked.
makes a single pass through the string; apart from
obtaining the needed font resources,
does not allocate memory or other resources. As a
DrawHTML() is lightweight and
is actually robust if what you throw at it is not
fully valid HTML:
many people forget to replace "&" by
"<" by "
A browser may skip the code or print the wrong
DrawHTML() will print
"&", "ü" and
"<" if they appear in the string. This
way, you can display strings with
without taking extra care for reserved characters
like "&" and "<".
Using the code
The function prototype
DrawHTML() is the same as that of the
standard Win32 SDK function
In your program, you would use
just like you would use
code archive (see the top of this article)
contains a little demo program. The relevant
function is reproduced below:
static void Cls_OnPaint(HWND hwnd)
HFONT hfontOrg = (HFONT)SelectObject(PaintStruct.hdc,
SetRect(&rc, rc.left + Margin, rc.top + Margin,
rc.right - Margin, rc.bottom - Margin);
"<p>Beauty, success, truth ..."
"<br><em>He is blessed who has two.</em>"
"<br><font color='#C00000'><b>Your program"
" has none.</b></font>"
There is a bit of
scaffolding code around the call to
to offset the text from the frame of the window and to
select a bigger font. The font,
is created in the
(not shown). I used a 20-pixel high TrueType font to
better show the effects of italics and bold.
As I wrote already, the
HTML support by
is very limited:
- The only supported
are equivalent to
tag is only supported in the extent that you can
change the text color with it. It is also the only
tag that can take a parameter, and this parameter
should be "
with a value in the well known HTML hexadecimal
notation. For example, "
color='#ffff00'>" (this is yellow, by
- With the exception
of tags that take parameters (currently only the
tag), there may be no spaces in the tags;
is okay, but
align='right'> will be considered as two
words "<p" and
"align='right'>". That's right: when
considers that something is not a valid HTML
tag, it prints it as a word.
- Any special
are unsupported, you must just type in the correct
characters. That is, you can just use the characters
"à" and "&" in the text,
and "<" too.
Points of Interest
is Unicode-compatible, but in a way different than a
web-browser does it: instead of using an 8-bit encoding
for the Unicode data (UTF-8), you just pass in a
"wide character" string. To have Unicode
support, you should compile the
source code with the
The code for
consists of three blocks:
- There is a simple HTML
parser. The parser is fairly strict, and it has a
fall-back in that everything that it does not
recognize is "plain text". This includes
unknown tags, and there
differs from browsers, which ignore unknown HTML
- The text drawing
function, which outputs text word for word, and
handles line breaking and the calculation of the the
size of the bounding box.
- A simple small color
stack for the colors set with the
tag. When changing a color, the old color must be
saved somewhere, so that the
tag can restore it. Hence, the stack.
A few "formatting
flags" of the
function are not supported by
These are related to alignment (horizontal and vertical)
and to setting TAB stops. Supporting horizontal and
vertical alignment requires an extra pass over the text,
to get the full height and the width of each individual
line. Specifically, the following formatting flags of
function are not supported:
|align text lines
to the right border
characters (to 8 spaces)
These three flags are
ignored if they are set. The "&" character
is never a "prefix character" in
DT_NOPREFIX flag is not necessary.
More noteworthy, in
fact, is that all the other flags are supported,
specifically the flags
causes the tags
to be ignored, and
calculates the bounding rectangle for the text without
actually drawing it. Compatibility with
is furthermore improved by using
in the back end to actually draw
the text after having parsed the HTML