viksoe.dk

Simple HTML Viewer

Simple HTML Viewer

Written by Bjarke Viksoe.
This article was submitted .


I tend to need rich font/color-formatted labels in my applications, so I usually end up embedding an Internet Explorer control to give me some display freedom. It is however somewhat frustrating to see load performance and resources vanish while IE is loading into my app.

A good alternative is to use the RichEdit control. The RichEdit control is actually capable of displaying text almost as nicely formatted as an HTML engine. It is also relatively light-weight, although it also supports a COM object model and various printing facilities.
Unfortunately, the RichEdit control requires Rich Text Formatted (RTF) text, which I find is a bit more difficult to master than HTML.

So I build a simple HTML to RTF converter, which knows of basic text formatting, tables and layout. I also extended a RichEdit text control with a Load(HTML) method, added the converter to transform the HTML input into RTF and presto: Enter the Simple HTML Viewer control!

This new control is a regular RichEdit control, but one that accepts HTML as input. It renders the text as close as possible to the Internet Explorer browser - allowing you to have a variety of text formatting styles with a light-weight text control.

HTML tag support

The converter scans the HTML document and ignores most of the tags (the ones that it does not understand). It picks out a few of them and uses them as formatting codes. Some tag attributes and even a few style attributes are supported.

The following tags are supported:

<BODY>...</BODY>
The HTML body. The tag supports the following attributes: BGCOLOR="#rrggbb", LEFTMARGIN=n, TOPMARGIN=n, RIGHTMARGIN=n and BOTTOMMARGIN=n. You can omit both the <BODY>, <HEAD> and <HTML> tags if they are not needed.

<B>...</B>
The bold text format.

<I>...</I>
Formats text in italics.

<U>...</U>
Prints underlined text.

<FONT>...</FONT>
The font tag with several attributes, such as FACE="xyz", SIZE=n and COLOR="#rrggbb".

<BR>
A single line-break.

<P>
The paragraph tag.

<A>...</A>
The anchor (link). The HREF="xyz" attribute is included, and with a RichEdit version 2 control you receive standard EN_LINK notifications. Use the ExtractLink() method to retrieve the link's URL.

<SPAN>...</SPAN>
A formatted text strip. Supports the following style attributes: BACKGROUND-COLOR: #rrggbb and COLOR: #rrggbb.

<DIV>...</DIV>
A line-breaking text strip. Supports the following attribute: ALIGN="xyz". And these style attributes: BACKGROUND-COLOR: #rrggbb and COLOR: #rrggbb.

<TABLE>...</TABLE>
A simple table construct. Only a fixed layout is supported. It recognizes the BORDER=n attribute and the TABLE-LAYOUT: fixed style attribute. The following tags are required in a table construction: <COL>, <TR> and <TD> tags. The use of the <COL> tags is not optional. And remember to specify the fixed layout.

Tables are a pain to do well in RTF. As the RTF specification says, "tables are probably the trickiest part of RTF to read and write correctly.". My control only supports tables with fixed layout (columns with fixed width) and, as you can see, only a few table modifiers are implemented.

Microsoft doesn't support the entire RTF specification so you will never be able to produce documents entirely as cool as in HTML. Also the RichEdit control blows up when you feed it with malformed RTF, so make sure to close your HTML tags properly.

Images are still not converted. It would be nice to have them embedded in the document, but that's another task...

Feel free to extend the HTML support yourself.

How to use it

If you need it in a dialog, then the MSVC++ resource editor doesn't seem to support RichEdit version 2 by drag'n'drop. However, you can manually change the classname to RichEdit20A in the resource file once you have dragged a RichEdit version 1 control to the dialog.

Now add a member variable to your dialog implementation file...

  CSimpleHtmlCtrl m_ctrlHTML
In the OnInitDialog() event handler, add the following lines:
LRESULT OnInitDialog(UINT /*uMsg*/, 
                     WPARAM /*wParam*/, 
                     LPARAM /*lParam*/, 
                     BOOL& /*bHandled*/)
{
  ...
  m_ctrlHTML.SubclassWindow(GetDlgItem(IDC_RICHEDIT1));
  m_ctrlHTML.LimitText(10000);
  m_ctrlHTML.Load("html stuff goes here...");
  ...
}

And do remember to initialise the RichEdit library properly in your application startup code.

int WINAPI _tWinMain(HINSTANCE hInstance, HIN...)
{
  ...
  ::InitCommonControls();
  HINSTANCE hInstRich = 
       ::LoadLibrary(CRichEditCtrl::GetLibraryName());
  ...
  int nRet = Run(lpstrCmdLine, nCmdShow);
  ...
  ::FreeLibrary(hInstRich);
  ...
  return 0;
}
Also remember to set the following macro...
#define _RICHEDIT_VER 0x0200
in stdafx.h because the RichEdit control version 2 has better support for RTF.

Some older Windows machines (Win95?) comes with a rotten RichEdit v2 control. Microsoft is not providing an easy download for this component so you may want to stick with version 1.

Notes

If you just intend to use a RichEdit with pure RTF, it can be useful to use the Wordpad text-editor to type in the text and save the contents as a RTF file. Wordpad tends to keep the RTF size down, while other word processors may add a lot of unused formatting bloat.

Source Code Dependencies

Microsoft Visual C++ 6.0
Microsoft WTL 3.1 Library

Download Files

DownloadSource Code (8 Kb)

To the top