WinHelp versus HtmlHelp code

Here are the simple instructions for converting C/C++ code for Vista help.

Most Windows programs have simple help requirements, and the WinHelp() function within the Win32 API used to provide all of the necessary functionality. Although the documentation shows 18 different instructions, most common operations boil down to one of three primary functions: displaying the help file with a default topic, showing the contents of the help file, or displaying a specific help file topic.

WinHelp ( window, “filename.hlp”, HELP_CONTENTS, NULL )
WinHelp ( window, “filename.hlp”, HELP_INDEX, NULL )

These commands show the default contents (a.k.a., index) page of a help file. In Win32 projects, these commands are identical, the latter remaining from an older (16-bit) incarnation of Windows Help. Contrary to implications in the documentation, these are not superseded by the HELP_FINDER command; these display a default help page, whereas the “preferred” method (below) shows a separate keyword index.

WinHelp ( window, “filename.hlp”, HELP_FINDER, NULL )

This command shows a keyword index for a help file, which generally means that it opens the “Contents” tab with a scrollable list of keywords. In Win32 projects, the HELP_KEY command can also be used to open the “Find” tab, although this use was unusual except as a leftover from older (16-bit) projects.

WinHelp ( window, “filename.hlp”, HELP_CONTEXT, context )

This command shows a specific page of the help file, based on the ‘context‘ parameter. This is the standard and straightforward method of providing context sensitive help.

Of course, there are other WinHelp commands, and each use will need to be individually evaluated. However, if a project still uses the HELP_HELPONHELP command, then it can probably be removed completely, along with any menu option or other element that invokes it. This opens a generic help page, “Help Topics: How to Use Help”, which is truly one of those seemed like a good idea at the time situations. I would be surprised if any Windows user, ever, opened this help topic in earnest (though quality assurance sure did).

Now, along comes Windows Vista, which no longer supports WinHelp, and instead essentially forces us to use the HtmlHelp() function. The newer HTML Help (.CHM) files now (usually) show the help files in a dual-pane window, with the “Contents” and “Search” tabs on the left and the help page on the right. This means that the 19 listed HtmlHelp commands (which omits HH_HELP_FINDER) can be distilled down to only two basic calls.

HtmlHelp ( window, “filename.chm”, HH_DISPLAY_TOC, NULL )

This command displays the default help topic, and since the index and search features are contained in the left pane, this allows access to all of the basic help functionality. This can replace any WinHelp calls using HELP_INDEX, HELP_CONTENTS, or HELP_FINDER, and may allow some interface simplification if there is duplication among these commands.

HtmlHelp ( window, “filename.chm”, HH_HELP_CONTEXT, context )

This command displays a specific page of the help file, based on the ‘context‘ parameter. This is a direct replacement for WinHelp calls using HELP_CONTEXT to provide context sensitive help.

Incidentally, the HTML Help API is the most poorly documented common API that Microsoft supports. The HtmlHelp() function, the heart of the API, does not even have a normal help page itself, like every other Win32 function. To get the header and import library files, one needs to download either the Platform SDK (up to 400M), or the HTML Help 1.4 SDK, which is alternately (and confusingly) identified as HTML Help Workshop 1.3 or 1.31. Everything about this feels like an afterthought.

Once the HtmlHelp() calls are in the code (or before, if you prefer), two additional changes need to be made to the C or C++ code. First, the header file (htmlhelp.h) needs to be included:

#include <htmlhelp.h>

Then, the import library, htmlhelp.lib, needs to be added to the project. Normally, this would be done in the “Link” section of the project settings. However, just for giggles, here is a line of code that will add the necessary library to the list of default libraries for a particular object file (in Visual C++):

#pragma comment ( lib, “htmlhelp” )

With the header file included, your code should compile, and with the import library added (via either settings or pragma), it should link as well. This, of course, assumes that the development system already has these file available to the compiler and linker, respectively (and if not, see the download link above).

Well, that is pretty much all there is to converting WinHelp source code to HTML Help to provide support for Windows Vista. Of course, one should always check return values and perform proper error handling. In the above cases for HtmlHelp, the return value is an unnecessary window handle in the first case, and not documented at all (told ya!) in the second, so casting the return value to “(void)” may be acceptible.

Finally, the sketchy HTML Help API documentation could lead one to implement HH_INITIALIZE and HH_UNINITIALIZE commands, which in turn would require a HH_PRETRANSLATEMESSAGE command to be inserted into the program loop (to allow the help window to function). Our research suggests, and testing confirms, that this extra work is only necessary if one is using embedded help and, hence, need to force execution to a single thread. (Reference KB194116 and comments by former Microsoft help developer, Ralph Walden.) Likewise, it is also unnecessary to use the HH_CLOSE_ALL command on program exit, as HTML Help will automatically close the help window.

Any questions?

Leave a Reply

Your email address will not be published.