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 Files\HTML 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 Files\HTML Help Workshop\include
  • Under Show directories for choose Library files, click on New and type
    C:\Program Files\HTML Help Workshop\lib
  • Under Show directories for choose Executable files, click on New and type
    C:\Program Files\HTML 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 create a directory called Web. Publish 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 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
(Custom Build tab)
Description Making HTML Help File...
  Commands hhc.exe html\$(InputName).hhp
copy html\$(InputName).chm $(OutDir)\$(InputName).chm
  Outputs html\$(InputName).chm
  Dependencies... html\$(TargetName).hm
(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");
    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:


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 "Web\about.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.


Download demo project - 126 KB


  • Problem with oppenning HTML with CWinApp::OnHelp()

    Posted by leykl on 06/12/2006 03:53am

    First of all thanks for a good description and explanation. I am working on VC7. I have added: "EnableHtmlHelp();" and the free((void*)m_pszHelpFilePath); m_pszHelpFilePath = _tcsdup(_T(".......chm")); When i try to run it, i get "Failed to Lunch Help" The strange thing that if i use with CWinApp::OnHelpFinder then it works propperly. ON_COMMAND(ID_HELP, CWinApp::OnHelpFinder) - works. ON_COMMAND(ID_HELP, CWinApp::OnHelp) - doesn't work What could be the problem? Thanks

    • Problem

      Posted by Franek on 10/13/2006 05:38am

      Same for me but even with this command, i don't have anything...What could be the problem ?Thanks

  • You don't need MAKEIDH.EXE

    Posted by amcewen on 03/10/2006 03:38am

    Providing the /h parameter to makehm will generate the "#define" prefixes in the header file, which means that you no longer need to process the header with MAKEIDH.EXE.

  • problem with hhctrl.ocx

    Posted by David Best on 04/28/2005 08:29am

    Has anyone had a problem with the latest version of hhctrl.ocx (5.2.3790.233 (srv03_gdr.040918-1552))?
    I'm finding that when this version is present on the PC (probably updated automatically by the windows update process), my contents pages won't display.  I have to revert back to the version 5.2.3735.0 and then it's ok again.

  • Bad Link

    Posted by TSYS on 01/04/2005 12:01pm

    The link to download the HTML Help Workshop is bad. I found it at:

  • Not quite correct about MFC

    Posted by hypersw on 04/23/2004 11:48am

    Nicely written about HTML Help, but the methods suggested for displaying it in MFC are not quite correct. You should open the constructor of your CWinApp-derived class (eg CMyApp::CMyApp) and add a sole line there: EnableHtmlHelp(); That would do everything you need! Replace .htm to .chm in the path, call CWnd::HtmlHelp instead of WinHelp on F1, and a dozen other useful things. Try it out :)

    • Even like this

      Posted by Franek on 10/13/2006 05:31am

      Hello I'm working on MFC with VC7 and even like this, meaning with EnableHtmlHelp() and others,i do not have my help file displayed.Instead i've got "Failed to launch help"... Could you help me please ?Thanks

    • But correct in VC6 ...

      Posted by jov on 04/23/2004 02:15pm

      The article was written for VC6 - see the comment at the top. EnableHtmlHelp() was introduced in VC7 (Visual Studio .NET 2002).

  • Better solution for MAKEIDH.EXE

    Posted by ausafmalik on 03/26/2004 05:10pm

    First of all thanks Joep for a good description and explanation. It really helped me. 
    Here is a better solution that replaces the need of MAKEIDH.EXE
    Put this in the custom build step of resource.h for generating the .hm file:
    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"
    echo. "replacing IDH_ with #define IDH_"
    SET replace=
    FIND /V "#define" < html\$(TargetName).hm > html\$(TargetName).hm1
    FOR /F "tokens=1 delims=" %%i IN (html\$(TargetName)hm1) DO (
      echo. %%i
      SET replace=%%i
    FIND "#define" < html\$(TargetName).hm >> html\$(TargetName).hm2
    DEL html\$(TargetName)hm1
    MOVE /Y html\$(TargetName).hm2 html\$(TargetName).hm
    GOTO End
    echo.%replace:IDH_=#define IDH_%>>html\$(TargetName).hm2
    :) Malik

    • Can I use this for something else?

      Posted by ajtruckle on 05/26/2004 02:03am

      I have not got this to work for myself yet. I would like to use it. But can I also use it to create a cshelp.h file which also has the IDH_ prefixes (but only for ID_ and IDC_ and that the numbers are left as integers and not hexadecimal. Is this possible? Thanks.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date