Starting with HTML Help

.

Environment: This demo is made with MS Visual C++ Version 6.0 with the latest
Service Pack. It does NOT work under earlier versions of MSVC++.

One day I woke up and found myself wanting HTML Help in my project. So I started
searching for docs on using it with MFC and found out that it wasn’t as simple as I
thought. All I wanted was one entry in the Help menu (Help Topics…) and a Help button in
each dialog which would bring up the corresponding topic. And a nice contents pane in the
Help of course so users could get a quick overview and easily navigate through Help.

For those of you who want to get started with HTML Help my explorations might be
useful. For those of you who know of better or more ways to use it: let the world (and
me!) know. For those of you who think "What in the world is HTML Help?" look at
the Help in Internet Explorer 4.01 and you’ll know.

Using HTML Help splits up in a few sections. On each of which I’ll tell you the way I’m
doing it.

Installing the HTML Help Authoring
Kit

You can download the latest version for free here. I’ll
assume you install it in C:Program FilesHTML Help Workshop.
After installing you should prepare DevStudio: go to Tools, Options, Directories,
then:

  • Under Show directories for choose Include files,
    click on New and type
    C:Program FilesHTML Help Workshopinclude
  • Under Show directories for choose Library files,
    click on New and type
    C:Program FilesHTML Help Workshoplib
  • Under Show directories for choose Executable files,
    click on New and type
    C:Program FilesHTML Help Workshop
  • Close DevStudio and restart to save the changes.

Creating the topic files in HTML
language

First, of course, you’ll have to create the .htm topic files themselves. I like WYSIWIG
on this so I am using Frontpage Explorer to create a web which will contain all of the
files. Besides the .htm files you can add images, avi’s, sounds, just about anything you
want to use. The help file later on will behave like a website. You can also use one of
Frontpage’s themes if you want.

I do use a theme but I do not use the navigation features of Frontpage. The resulting
buttons on each page take up to much space in the Help window. Besides that, I make use of
the contents pane of the HTML Help. Navigating through a Help file by means of a Table of
Contents pane is, in my humble opinion, much more clear to the user than criss-cross
navigation with buttons on each page (when you use a theme you should add each .htm page
to the navigation pane (all on the same level) and rename it. The themes use these names
then for the page titles).

Under your project main directory create a directory called HTML.
In HTML crea
te a directory called Web.
P
ublish the Frontpage web you’ve created to Web. Frontpage puts
all sorts of files in here but the HTML Help Compiler will only include the files you and
the pages you made refer to so don’t bother about that.

Making the help file (.chm) itself

Start HTML Help Workshop, click on New, Project,
Next. Browse to the HTML directory, type yourname,
click Open, Next, Next, Finish. Click on Add/Remove
Topic Files
, Add, and browse to the Web directory. Select
all the .htm files you’ve created and click Open, OK. Click on HTML
Api Information
, Header File and type yourname.hm. This
will become the file with context ID’s from the project. Ignore the warning from HTML Help
Workshop and include the file anyway. Click on OK. By now you should have added a
[FILES] section with the topic files and a [MAP] section
with the header file in it.

There are many other things you can do. I’ve included a complete
published web in the demo project so feel free to look into the HTML Help project file.

Creating a MFC project

When you create a MFC project with AppWizard you can choose for Context
Sensitive Help
. When you do this there will be a hlp directory in
your project’s main directory and a MakeHelp.bat. You won’t need any of
these files for HTML Help so leave the Context Sensitive Help unchecked.

The HTML Help Project has to be added to your project, just like
the old WinHelp project. Quite a bit of manual changes to the project settings I’m afraid.
Start with adding the HTML Help Project File: from DevStudio’s menu choose Project,
Add To Project, Files. Browse to the HTML directory, select the .hhp
file and click OK. Now you can change the settings for your project. From the
menu choose Project, Settings, All Configurations. Then make
the following changes:


Setting for: Field/Button: Type:
Link tab Object/library modules htmlhelp.lib
yourname.hhp
(Custom Build tab)
Description Making HTML Help File…
  Commands hhc.exe html$(InputName).hhp
echo.
copy html$(InputName).chm $(OutDir)$(InputName).chm
  Outputs html$(InputName).chm
  Dependencies… html$(TargetName).hm
Resource.h
(Custom Build tab)
Description Making HTML Help Include File…
  Commands makehm ID_,IDH_,0x10000 IDM_,IDH_,0x10000 resource.h
>>"html$(TargetName).hm"
makehm IDP_,IDH_,0x30000 resource.h >>"html$(TargetName).hm"
makehm IDR_,IDH_,0x20000 resource.h >>"html$(TargetName).hm"
makehm IDD_,IDH_,0x20000 resource.h >>"html$(TargetName).hm"
makehm IDW_,IDH_,0x50000 resource.h >>"html$(TargetName).hm"
echo. >>"html$(TargetName).hm"
MakeIDH "html$(TargetName).hm"
  Outputs html$(TargetName).hm

and click on OK. Finally add the statement #include
<htmlhelp.h>
to your stdafx.h.

Comments on the custom build command for
resource.h

I make use of the utility MAKEHM that comes with MSVC. It creates a file with
renumbered ID’s corresponding to the resource IDs in your RESOURCE.H. When you create a
project with AppWizard and switch the Context Sensitive Help on you’ll get a MAKEHELP.BAT
file which calls MAKEHM and creates a .hm file with all your resource ID’s mapped to
another value in lines like HIDR_MAINFRAME 0x20080.

For some reason the gurus at Microsoft decided to do it differently in HTML
Help. Somewhere in the MSDN docs I found the note "If you used the IDH_ prefix for
your context-sensitive help topic IDs, HTML Help Workshop automatically compares the topic
IDs in your compiled help file against those mapped to numeric values in your project
file. Compiler messages will tell you where your context-sensitive help is broken so you
can fix it." That’s the reason I use IDH_ as a prefix only. The custom build command
creates lines like IDH_MAINFRAME 0x20080.

Another decision the MS gurus made is that this wasn’t good enough for HTML
Help. There must be a #define in front of the ID. That’s why I wrote a small utility named
MAKEIDH. You’ll find it in the main directory of the demo project. It parses a file and
places #define in front of every line that starts with IDH_. Final result for the .hm
file: #define IDH_MAINFRAME 0x20080. Copy
the utility MAKEIDH.EXE to a subdirectory anywhere in your path to have it always
available.

Implementing help calls

By now your project should compile without errors. There are a few changes to do in the
source files. First, in InitInstance(), change the default
file extension for the help file from .hlp to .chm:

    // Change extension for help file
    CString strHelpFile = m_pszHelpFilePath;
    strHelpFile.Replace(".HLP", ".chm");
    free((void*)m_pszHelpFilePath);
    m_pszHelpFilePath = _tcsdup(strHelpFile);

Then add a help handler in CMainFrame. Put the following in CMainFrame just before END_MESSAGE_MAP and outside the AFX_MSG_MAP tags:

    ON_COMMAND(ID_HELP, CMDIFrameWnd::OnHelp)

or, if you chose for single document view:

    ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)

Use ClassWizard to add an override for WinHelp. Replace the contents of WinHelp() by:

    HtmlHelp(m_hWnd,
AfxGetApp()->m_pszHelpFilePath, HH_HELP_CONTEXT, nCmd == HELP_CONTEXT ? dwData : 0);

Almost ready! When you compile your project now and press F1 or choose Help
Topics
you’ll get the warning HH_HELP_CONTEXT called without a [MAP] section.
The last thing you have to do is to map, in HTML Help Workshop, topic ID’s from the
generated .hm file to topic files. To have the help system react on F1 in the
main window you would map IDH_MAINFRAME (single document view) or IDH_HTMLDETYPE
(in my demo project with multiple document view) to INDEX.HTM. To show
specific help for a dialog just add a button with an ID of ID_HELP to the
dialog and map the corresponding translated dialog ID to the specific topic file. In the
demo project I added a button to the About box so I mapped IDH_ABOUTBOX to ABOUT.HTM.

In HTML Help these mappings are called aliases. Open the HTML Help Project with HTML
Help Workshop and doubleclick on the [MAP] section. Click on Alias,
Add and type the ID in the first field. Select a topic file in the second and
click OK, OK.

Using bookmarks

You can force HTML Help to scroll directly to a specific spot on a help page by adding
a bookmark to the HTML file. Just add a bookmark to the HTML Help file and add a # and the
name of the bookmark to the alias in HTML Help Workshop. In the demo project I’ve added a
bookmark in ABOUT.HTM. Click in the demo on Help, How to use
bookmarks
to view the effect.
The compiler now generates a warning that can be ignored (in this case HHC3015: Warning: An alias has been created to
"Webabout.htm#Bookmark" but the file does not exist
).

Distributing HTML Help

HTML Help works through a control called HHCTRL.OCX. When you want to distribute your
program with HTML Help, the user should have installed the latest version. Personally I
state that users of my programs should have Internet Explorer 4.01 installed before they
are able to use them. Then I’m sure they have HTML Help installed (and a recent
COMCTL32.DLL, also handy). On the Microsoft web you can find information about updates for
HTML Help called HHUPD.EXE. It can be implemented in a silent way (hhupd /q) in your setup
program so you’re sure they always use the latest HTML Help control.

Known problems and updates

  • Some readers couldn’t get the demo working: the message HH_HELP_CONTEXT called
    without a [MAP] section
    keeps popping up. This seems to be caused by the sequence
    in which the files are compiled (if the .chm file is build before the .hm file, the help
    file doesn’t contain updated ID’s). When the project is rebuild twice, the error message
    disappears. To ensure the .hm is build before the .chm file go to Project Settings,
    Settings, choose All Configurations, select the .hhp file, click on Custom
    build
    , Dependencies and add html$(TargetName).hm.
    This article (see Creating
    a MFC project
    ) as well as the demo project is updated with these changes.
  • Jayant Umrani wanted the following:
    (quote) HOW TO GIVE KETWORD SEARCHES DIRECTLY FRON VC++. SUPPOSE THE USER
    PRESSES F1 KEY WHEN HE IS SOME FEILD OF THE DAILOG BOX AND IDH IS ASSOSIATED TO SOME HTML
    FILE BUT THE ACTUAL TEXT IS DEEP BELOW IN THAT HTML, THEM THE HELP SHOULD ME SHOWN WITH
    THAT PART ON TOP
    (unquote). A few hours later he supplied the
    solution himself so I implemented it in the demo project and updated this article (see Using bookmarks).
    Thanks for participating!

Well, that’s it! Hope you find it useful.

Downloads

Download demo project – 126 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read