MS HTML Help‎ > ‎

HH Tips & Tricks


Linking to External Files

How to link from a Topic inside a CHM help file, to a file outside the CHM:

See also

 

Running Applets/Media Player etc in a HH Window

Some applications/controls/technologies cannot read files embedded inside a CHM file.  To run an Applet in a HTML Help window you must leave the applet files outside the CHM. Similarly if you embed Windows Media Player control in a HH window, the media files (.MID, .WAV etc) must be left outside the CHM (Media can be read by DOM but apparently not an embedded media control).

How's it done?  See demo_ext2.zip attached to the page  (if you don't have Java installed then only Example 3 will work).
Note: The script has been update -- See below Script to External File (below)

Note: Embedded Videos can be run from a CHM page. Here's a tip from Wizard Alexander Halser:

Automatically start AVI video when the topic opens:
 
 <img start="FILEOPEN" loop="1" DYNSRC="movefile_test.avi">
 
An MPEG video with sound that starts playing when you move the mouse over
it (appropriate decoder must be installed, of course):
 
 <img start="MOUSEOVER" loop="1" DYNSRC="dragdrop_videosample.mpg">

 Macromedia Director and Shockwave Flash Viewer:

Director files need to also go outside the CHM as well. Shockwave Flash on the other hand embeds nicely. Although please note that Flash player 6.0 (original release) broke embedding in CHMs for a little while until they fixed the problem in the 6.0.40.0 release (also know as 6.0 revision 40). Note also that multiple SWF files (normal Flash with no XML) that load each other work OK.

Camtasia

2/10/2004 - TechSmith Camtasia Flash files do not work inside a CHM file. Probably because the XML support file can not be found while inside a CHM file.

I found if I left the Camtasia HTML, XML, SWF outside the CHM and dynamically created a path to this external HTML (see download example above) then I could in fact make the Camtasia Flash run inside the HH window (or use Target="_blank" and make it open in a separate IE window).

 

<SCRIPT Language="JScript">
var path = GetCurrDir();   //See script in download link above
if (path != '')
  path = path + '\\';

document.writeln(' <p><a href="' +path+ 'Camtasia\\Flash_noscript.html">
   Open Camtasia file in HH window (External HTML)</a> ')
document.writeln(' <p><a href="' +path+ 'Camtasia\\Flash_noscript.html" target="_blank">
   Open Camtasia file in new Explorer window (External HTML in new window)</a> ')
</SCRIPT>

 

Script to External File ( Updated 4-Mar-2005)

Here is my script for linking to a file outside in the CHM folder. 
This script dynamically creates the HH Shortcut code with full paths to the external file and any param.

Try not to rely on relative paths and the Current Directory being always set correctly. Far better to use code like this that dynamically creates the full path to the external file on the fly.

// Return current dir -- 
// returns "" if in a browser 
// returns full path to CHM folder if in a CHM (with trailing \\)
// If in browser then - location.href=file:///d:/path/file.htm
// If in CHM then - location.href=mk:@MSITStore:D:\path\help.chm::/file.htm

function GetChmDir() {
  var X, Y, sl, a, ra, dir;
  ra = /::/;

  a = location.href.search(ra);
  if (a <= 0) //not a CHM - return an empty string
  return("");

  //find the index of the first colon in the string
  X = 0;
  ra = /:/;
  a = location.href.search(ra);
  if (a == 2) X = 14; //prefix = mk:@MSITStore:
  else 
  if (a > 2) X = a+1; //prefix = ms-its: OR prefix = its:

  //find last back slash
  sl = "\\";
  Y = location.href.lastIndexOf(sl);
  dir = location.href.substring(X, Y);

  //UnEscape path - EG. Replace %20 with spaces - Return path with trailing \
  var dir2 = unescape(dir)
  return(dir2 + "\\");
}


//Define a HH Shortcut with full path to exe and param if passed
function DefineHHShortcut(SCID, ProgName, Params) {
  var AppPath = GetChmDir();
  ProgName = AppPath + ProgName;
  if (Params != "") Params = AppPath + Params;

  document.write('<object id="' +SCID+ '" type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width="14" height="14">');
  document.write('<param name="Command" value="ShortCut">');
  document.write('<param name="Item1" value=",' + ProgName + ',' + Params + '">');
  document.write('<param name="Window" value="">');
  document.write('</object>');
}
//Create a Shortcut
DefineHHShortcut("hhctrl, "MyProg.exe", "");

 

 

Thanks Tim Green (EC Software Documentation & Support) for sharing the following code which can also expand relative paths within a CHM.

 

// Parse relative links to external files from within a CHM to absolute paths
// Usage examples (backslashes must be double, spaces must be %20):
// <a href="javascript:void(0);" onclick="parser('..\\..\\Examples\\MyFile.pdf');">Relative link up</a>
// <a href="javascript:void(0);" onclick="parser('DocFiles\\MyFile.docx');">Relative link down</a>
// <a href="javascript:void(0);" onclick="parser('MyFile.doc');">Link in same folder</a>

function parser(fn) {
  var X, Y, sl, a, ra, stepsUp, path, pathSteps, link, p, w;

  // Locate a drive letter reference and calculate its position in string
  ra = /:/;
  a = location.href.search(ra);
  if (a == 2)
    X = 14;   //prefix = mk:@MSITStore:
  else 
    X = 7;    //prefix = ms-its: OR prefix = its:
  sl = "\\";
  // Calculate position of last backslash in string and extract absolute
  // path to the directory in which the CHM is stored
  Y = location.href.lastIndexOf(sl) + 1;
  stepsUp = fn.match(/\.\.\\/ig);
  path = location.href.substring(X, Y);
  // If there are any '..\' steps, trim them from the path and remove
  // the same number of path levels from the absolute path to the
  // current CHM folder
  if (stepsUp) {
    fn = fn.replace(/\.\.\\/ig,"");
    pathSteps = path.match(/(\\.*?)(?=\\)/ig);
    p=""; w=pathSteps.length-1; 
    for (var q = 0; q < stepsUp.length; q++) {
      path = path.replace(pathSteps[w],"");
      w--;
    }
  } 
  // Now combine the results to an absolute path -- no trimming needs to
  // be done if the file is in the CHM folder or below the CHM folder
  link = 'file:///' + path + fn;
  location.replace(link);
}


 

IE5.5 Embedded Files Bug Q245572

With Internet Explorer 5.5 you can no longer link to ZIP, PDF, etc files embedded inside the CHM file.  Some file types may be ok. The bug appears to be a side effect of a security fix released with IE5.5. 

The fix is to install 5.5 SP2 or leave the files outside the CHM as shown in the example above.

See MS document Q245572

 

Linking to Embedded PDF files

Many authors compile binaries (PDF, ZIP, DOC files) into CHMs and use standard HTML code to link to the file. E.G. <a href="myfile.pdf">View PDF</a>

Problem:

If the PDF viewer (Acrobat Reader) embeds into the HH window instead of opening in a separate window, you will see a blank topic window. This is an Adobe bug (says MS).

I have not tested this with latter version of Acrobat Reader. Please let me know if you have success.

Solution:

  1. You can turn off embedding from within Adobe Acrobat Reader Version 4 and 5.  Start Adobe Acrobat Reader and go to File | Preferences | General (Ctrl-K).  Then, unselect "Web Browser Integration". 
     
  2. Leave the PDF file outside the CHM and use the HTML Help shortcut command to open the PDF (the executable name is the PDF filename). This command only works inside a CHM.

    <OBJECT id=hhctrl type="application/x-oleobject"
    classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width=100 height=100>
    <PARAM name="Command" value="ShortCut">
    <PARAM name="Button" value="Text:Open PDF">
    <PARAM name="Item1" value=",Test.pdf,">
    </OBJECT>
     

Embedded Links Not Working?

If your embedded file links don't work at all then please see bug Q245572 above.

 

Keyword Mark-up using Meta Tags

Here is an undocumented method of adding Keyword mark-up using Meta Tags (instead of ActiveX mark-up).   That is, adding ALink and KLink info to topics, for the compiler to collect at compile time. KLinks are visible (as usual) and displayed in the Index tab with the other .HHK file items. This method is used with MSDN documents.

Examples from MSDN  (view source to see more):

<META NAME="MS-HKWD" CONTENT="Usage Peak counter">

For multi-level us a comma...

<META NAME="MS-HKWD" CONTENT="Page Faults, Job Object Details">

I found if you define a Keyword "xxx,yyy" then you must also define a keyword "xxx" somewhere as well, or the result could be a little strange.

A-keywords are defined similarly, but the name is "MS-HAID".

Note: The advantage here is this Keyword mark is NOT removed from the HTML document at compile time.

 

CHM To PDF (using multi-page print)

"Rhonda Bracey" (www.CyberText.com.au) has some great tips on creating PDFs from CHM files:
   http://www.cybertext.com.au/tips_HTML_pdf_from_chm.htm


Documentation Wizards Peter Lees and Adrian Green have post the following tips on creating PDFs from CHMs:

From "Pete Lees" <...>
Subject: CHM to PDF 
Date: April 2001

Here's a quick workaround that may work for you. (To give credit where it's due, I think Rob Cavicchio suggested this originally.)

=================

You can get a combined HTML file that contains all of the text in a
particular contents book as follows.

  1. Right-click the book and choose "Print".
  2. Choose "Print the selected heading and all subtopics".
  3. When the print prompt appears, ALT+TAB to Windows Explorer.
  4. Browse to your TEMP folder, and find the latest file of the pattern "~hh*.htm".  This is a concatenation of all the HTML files in the book you printed.
  5. Copy this file elsewhere before cancelling (or continuing) the print job, as the file will then be deleted.  If you have Acrobat installed, you can continue the print job to PDFWriter or Distiller to create a .PDF from these topics.

=================

To add to this: if you add a book heading at the beginning of the TOC and make all the following headings and pages subentries of it, you can use the above method to create an HTML file containing *all* the topics that have an entry in the TOC.

"Pete Lees"

From: "Adrian Green" <...> 
Subject: CHM to PDF 
Date: Tue, 22 May 2001 11:51:32 +1000 
 

The method I've been using is:

Install a Postscript driver that redirects its PS output to a file. 
eg: "HP LaserJet 5P/5MP Postscript"

Print the complete CHM. The PS driver will prompt for a PS file to  save to.

Then use the freely available "Ghostscript" & viewer software to convert the resulting postscript to PDF.
(incidentally I find Ghostscript's pdf reader to be a quicker &  smaller alternative to Acrobat reader)

Just thought I'd mention this - useful for people who do not wish to spend $$$ on Acrobat distiller. The above process is quick, free and has great results. The only drawback is loss of navigational links in the output.

Regards,
Adrian Green.

 

Fixing TOC Auto-sync

Problem #1:

When the TOC contains more than one occurrence of a filename, the auto-sync feature often jumps to the wrong item in the TOC.  This happens even if the files (with the same name), live in different CHMs.

Fix: #1

Firstly, try and limit the use of duplicate file names. Don't use the same name (eg. "Index.htm") in every folder. A prefix is a good idea. Example: Prefixing all files in the Reference CHM with "Ref_" will minimize problems between merged CHMs.

But sometimes we do need to link to a single file from several places in the TOC.

The following solution comes from wizard Rick Stone (eHelp MVP): 

Link to a dummy redirection file. This dummy file has a unique filename, no visible text and simply redirects the user to the correct topic. The redirection is not seen by the HH auto-sync.  Change all links, including URLs in your TOC, to point to the dummy file.

Example of a redirection file.  The <title> tag is optional.

<html>
<head>
   <title>Same title as main.htm</title>
   <meta HTTP-EQUIV=refresh CONTENT="0;URL=main.htm">
</head>
<body></body>
</html>

Tip: Try and use helpful filenames. Example: pxy_ref_main.htm   
The "ref_" prefix tells me the proxy is used by the Reference CHM. The "pxy_" prefix says it is a dummy proxy file.

Fix: #1 Take 2 - Here "Gabor Hojtsy" has taken Ricks solution and refined it:

Instead of creating many redirection files, just create one (_redirect.html) and pass it the file to redirect to in a bookmark. Here is _redirect.html...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>Redirect Page</title>
<script>window.location.replace(window.location.hash.substring(1));</script>
</head>
<body></body>
</html>

Links are in the form:

_redirect.html#page_to_jump.html
_redirect.html#other_page_to_jump.html

By using replace() in the JS code above, the redirect page won't be there in the history list, it won't clutter the back button list with useless pages. The JScript requires a minimum of IE4.

[Top marks Gabor]


Problem #2:

Many thanks Alexander Halser who reports that TOC Auto-Sync fails on the TOC Node that points to the Default Page, if the Node is non-binary and the first node in the TOC.

I have verified this is a bug, testing under Window XP SP1. Alex was able to duplicate this behaviour with different versions of HTML Help and MSIE on Windows 95, 98, 2000 and XP.

Description:

If you click a link that takes you to the CHM's default page, then TOC Auto-Sync will fail. 
IE. TOC auto-selection will not change to the Node that points to the default page.
This occurs under the follow conditions:

  • The TOC is compiled non-binary.
  • The Default topic is the very first node in the TOC.

Workaround:

  • Use binary TOC.
  • Make the Default topic something other than first node in the TOC.

 

Custom Icons

Problem:

HH allows you to customize the TOC icons by providing a strip of images in a BMP file. Unfortunately this feature was never fully completed and only works if you specify an absolute path to the BMP file.

Fix: #1

Ralph Walden: "If the graphic is on the same drive as the project file, the path is forced into a path relative to the project file -- unless it is prefixed with a file: protocol. That of course breaks your custom icons. The only workaround I can think of that is to prefix the path with file:\\ to prevent the compiler from converting the full path into a broken relative path, or to make certain that your project file is on a different drive then the BMP file."

MVP Rick Stone: "When you specify the icon strip file, ensure that it says c:stripname.bmp and not just simply do stripname.bmp. (note the absence of the typical backslash after c. This should work regardless of the folder the .CHM and strip are copied to, but it limits the placement of the .CHM on the C drive in order to use the custom strips. If the .CHM and the icon strip file are moved to E: for instance, it won't work."

<OBJECT type="text/site properties">
 <param name="ImageList" value="file://c:wwhelpicons.bmp">
 <param name="Image Width" value="16">
 <param name="Color Mask" value="0xff00ff">
</OBJECT>

Fix: #2

Rick Strahl's solution: Install the BMP to the windows folder (EG: c:\windows or c:\winnt) then use %systemroot% in the BMP path. Tip: Type "ECHO %systemroot%" at a DOS prompt.

<OBJECT type="text/site properties">
 <param name="ImageList" value="file://%systemroot%\wwhelpicons.bmp">
 <param name="Image Width" value="16">
 <param name="Color Mask" value="0xff00ff">
</OBJECT>

%ProgramFiles% could also be used. This environment variable contains the Program Files directory path. 
Example: "c:\Program Files".

 

Running Control Panel Applets

Question:

How do I open a control panel applet from HTML Help?

Answer:

Use the HH Shortcut command to run rundll32.exe. This windows file is in the windows search path so no directory info is required. You specify the CPL applet and page tab to open via command line parameters.

Parameters: shell32.dll,Control_RunDLL CPLfilename,@AppletNo,AppletPage

CPLfilename = name of CLP file - eg. "XXX.CPL" - Leave blank to show the control panel.
AppletNo = Specify which applet to run (zero based). 
   E.G. MAIN.CPL,@0 is mouse properties, while MAIN.CPL,@1 is keyboard properties.
AppletPage = CPL Applet page to display (zero based). Not always in a logical order.

The following reference was creating by observing my Windows 98SE system.

CPL filename Applet No Description
APPWIZ.CPL 0 Add/Remove Programs Properties
DESK.CPL 0 Display Properties
INETCPL.CPL 0 Internet Properties
INTL.CPL 0 Regional Settings Properties
JOY.CPL 0 Games Controllers
MAIN.CPL 0 Mouse Properties
MAIN.CPL 1 Keyboard Properties
MAIN.CPL 2 Printers Window
MAIN.CPL 3 Fonts Window
MMSYS.CPL 0 Multimedia Properties
MMSYS.CPL 1 Sound Properties
MODEM.CPL 0 Modems Properties
NETCPL.CPL 0 Network Properties
PASSWORD.CPL 0 Password Properties
POWERCFG.CPL 0 Power Management Properties
STICPL.CPL 0 Scanners and Cameras Properties
SYSDM.CPL 0 System Properties / Device Manager
SYSDM.CPL 1 Add New Hardware Wizard
TIMEDATE.CPL 0 Time/Date Properties
ACCESS.CPL 0 Accessibility Properties
TELEPHON.CPL 0 Dialling Properties
THEMES.CPL 0 Desktop Themes
TWEAKUI.CPL 0 Tweak UI
MSWEBCPL.CPL 0 Personal Web Server Properties
ODBCCP32.CPL 0 ODBC Data Source Administration
PREFSCPL.CPL 0 Real Audio Preferences

Example #1: Show just the Control Panel

<OBJECT id=hhctrl type="application/x-oleobject"
classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width=100 height=100>
<PARAM name="Command" value="ShortCut">
<PARAM name="Button" value="Text:Open Control Panel">
<PARAM name="Item1" value=",rundll32.exe,shell32.dll,Control_RunDLL">
</OBJECT>

Example #2: Show Mouse Properties, open at page 4

<OBJECT id=hhctrl type="application/x-oleobject"
classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width=100 height=100>
<PARAM name="Command" value="ShortCut">
<PARAM name="Button" value="Text:Mouse Properties - Page 4">
<PARAM name="Item1" value=",rundll32.exe,shell32.dll,Control_RunDLL MAIN.CPL,@0,3">
</OBJECT>

See also: http://webhelp.magrino.com/_shared/2001_11/2001_11_1.htm

 

Using RunDll32.exe

RunDll32.exe is a handy MS Windows OS component used to access functions in DLLs. The section above (Running Control Panel Applets) describes how to open a Control Panel Applet via a shell32.dll function. RunDll32.exe lives in %WINDIR% which is in the Windows search path so you don't need do specify the full path when executing RunDll32.exe.

MS Knowledge Base Article - 164787 describes the RunDll32 Interface.
 

Word HTML

Normally you would not want to use Word for HTML Help authoring. Word does not converted .DOC to .HTM very cleanly. Use a real HTML editor such as FrontPage.

If you must author in Word then use the free MS Office HTML Filter 2.0 tool.
http://office.microsoft.com/assistance/2000/htmlfilter.aspx
http://office.microsoft.com/Downloads/2000/Msohtmf2.aspx

Also, once compiled into HTML Help the images may not show. First send the HTML through the filter tool (above). If there is still a problem, then open the .HHP project file up in NotePad and add the images to the [FILES] section by hand. This ensures that the images are compiled into the CHM help file.

23-Aug-2003: Word 2002 (Office XP) has Filtered SaveAs

I just noticed that Word 2002 has an option in the SaveAs dialog to save as filtered HTML. So for Office XP forget the extra Filter application (thanks Linda Karma for pointing that out to me).

Excluding files from FTS

Problem:

It is easy to exclude a topic from an CHM Index. Simply don't declare the topic in the .HHK index file. Is there a way to exclude a topic from the Full-text search (FTS) (search tab of the HH window)?

Fix:

The HTML Help compiler parses any filename with a ".h" in the filename. So if you give the files you want to exclude say a ".xhtml" file extension then it wont be parsed for FTS information. I use ".xhtml" extension with no apparent downside.

The other way you could achieve this is to place all the non-FTS topics in one CHM and switch off the FTS feature for that CHM.

 

Persistence between Topics

Problem:

I want my CHM topics to save/share some state information. Cookies seem to work OK in uncompressed HTML but not in a compressed CHM.

Fix:

Rob Cavicchio posted the following to the HATT group:

After a fair amount of testing I performed today, I've concluded that the only deciding factor about how well cookies work in compiled Help files is the version of IE that is installed. This is true for both .chm and .hxs files; the same considerations seem to apply to both versions of Help. In brief:
  1. Compiled Help cookies don't work with IE 4, and there is no workaround (as far as I can tell).
  2. Compiled Help cookies don't work with IE 5.0, but the workaround of calling cookie functions in an HTML file external to the compiled Help file does work.
  3. Compiled Help cookies do work with IE 5.5 & IE6. No workaround is needed.
  4. Compiled Help cookies seem to have broken again in IE6-SP1. The workaround of calling the cookie functions from an external file does seem to work.

Pete Lees continues...

Regarding point 2) & 4) I think the technique to which Rob is referring is as follows:

  1. Along with your .CHM, install a plain HTML file.
  2. Put script functions to set and retrieve cookies into the HTML file <head>.
  3. In a .CHM topic from which you want to use cookies, create a hidden <iframe> (can be done with style="display:none;") that contains the external HTML file.
  4. From the .CHM topic, call the cookie functions within the hidden <iframe> using frame references (e.g., document.frames["hidden"].cookieGet();). Make sure to set an expiration date on the cookie if you want it to last between Help sessions.

MS IE5/6 Persistence (again thanks Pete Lees)...

Maybe you can achieve what you want using "persistence" (requires IE5 or above)? 
There is more information on this here:
http://msdn2.microsoft.com/en-us/library/ms533007.aspx

and there is a working example in the "Microsoft HTML Help Design Techniques" file that
Scott Boggan prepared for the 2001 WinWriters Online Help Conference, available from
http://www.winwriters.com/ohc01/suppmatl/index.html.

The other way to save information between pages in a CHM is to use an ActiveX control which can give you access to INI files or the Registry. I have a free DLL you can use at http://helpware.net/hwserver/. However, using such a DLL does raise the complexity of your help system. I would always recommend simple is best.

One more Tip (from Sven-Ola T ÿÿ ke):

You can also pass a string between pages using window.name, as this property is normally empty unless you are calling a function like window.Open(). This is an undocumented feature and has been around since IE3.

http://msdn2.microsoft.com/en-us/library/ms536651.aspx
http://msdn2.microsoft.com/en-us/library/ms534187.aspx

 

Error HHC6000 & HHC5007

Problem:

After converting a Word DOC to HTML the Help compiler gives errors

HHC6000: Error: An internal file could not be created. Make certain there is enough disk space on the drive where you are compiling your file.
HHC5007: Error: Fatal navigational compilation error. This is likely the result of an invalid contents (.hhc) file.

Fix: From Pete Lees

These error messages commonly appear if the heading tags in your HTML files contain any parameters other than the actual headings. For example, this would work:

<H1>My heading</H1>

but this wouldn't:

<H1 align="center" >My heading</H1>

Fix: From Ulrich Kulle

In another cause you'll get these two error messages if you have a contents (.hhc) file that doesn't contain any TOC entries. If you add a single entry and then recompile, the messages should disappear.

You can also get these error messages if you choose the option to auto-generate the TOC -- in HTMLHelp Workshop, you do this by selecting the checkbox "Automatically create contents (.hhc) file when compiling" on the Files tab of the Project Options dialog box -- *and* you haven't any <h1>, <h2> tags in your HTML files *or* the heading tags in your HTML topic files contain one or more attributes.

So, please check your HTMLHelp Workshop properties and uncheck the checkbox (see above).

 
Protecting CHM Content

Problem:

What are my options in terms of securing a CHM from unauthorized access and copying?

Fix: (Posted by Pete Lees - thanks Pete)

Unfortunately, I don't think .chm files were designed to be secure, and there is nothing to stop anyone from decompiling them.

There are a few other techniques that you could experiment with, including:

1) Preventing users from selecting the text in a help topic and viewing the source of the topic. You can find instructions on how to do this in Simons' Help Tips file available from http://www.simon-jones.org.uk/help.htm

2) Using an HTML encrypter such as the one available at http://htmlcrypt.cedium.net (thanks to Rick Stone for drawing our attention to this). One slight drawback is that the encrypted HTML files don't show up in the results of a full-text search.

 

Run Script from HH Toolbar Button

Problem:

How can I make a HH toolbar button run some script?

Fix: (Posted by Pete Lees - thanks Pete)

You can do this by linking the Jump button to a topic that contains the script. Then, using the onLoad event in this topic's <body> start-tag, you can execute the script automatically when the topic loads. 
For example:

<html>
<body onLoad ="JavaScript:alert('Hello');history.back(1)">
</body>
</html>

The purpose of the "history.back(1)" method is to ensure that the most recently-viewed topic remains in the topic pane and isn't replaced by a completely blank topic.

 


Programming Tips

HH_CLOSE_ALL Bug and HH_INITIALIZE

Problem:

Marcel van Brakel has uncovered a real problem with HH_CLOSE_ALL. When you call HH_CLOSE_ALL on shut down, the HH API creates another thread and sometimes does not return until after you have performed UnLoadLibrary(hhctrl.ocx). In this case the HH_CLOSE_ALL thread returns to nothing and causes an access violation.

Discussion:

Ralph Walden (x-Microsoft) describes the problem:

The switch to a background thread was done after I left (the MS help team)  in order to solve a problem with Visual Studio. I knew they should have fixed Visual Studio instead of "fixing" HTML Help (which wasn't broken). I've never actually tried it, but along with that change was a hack that allowed you to call the API in a way that it would create an interface, and then you'd call the API again to release that interface. You start off with HH_INITIALIZE and end with HH_UNINITIALIZE. Another alternative would be to set the HH_GPROPID_SINGLETHREAD property to TRUE -- that might get HTML Help back onto the parent's thread.

Fix:

  • As described by Ralph above, you can try using the HH_INITIALIZE, HH_UNINITIALIZE commands. These are documented in the HH Workshop online help.
  • Call HH_CLOSE_ALL earlier. Get more space between the HH_CLOSE_ALL and your call to UnloadLibrary. In VB and Delphi you would perform the call on the Form QueryUnload _not_ on the Form Close or Destroy.
  • Marcel van Brakel seemed to fix it by calling Sleep(0); immediately after the call to HH_CLOSE_ALL. Again providing more time for the rogue thread to return.

More Tips:

Here is an alternative to using HH_CLOSE_ALL. What I do with my applications is keep the handle of the HH Windows when making a help call: _HHwinHwnd := htmlhelp(...) and on shutdown call:

if IsWindow(_HHwinHwnd) then
   SendMessage( _HHwinHwnd, wm_close, 0, 0 );

This is 10 times faster code, and eliminates the need for HH_CLOSE_ALL completely.

Also, as programming wizard Roland Mechling points out, don't blindly call HH_CLOSE_ALL on shutdown. If a user does not have HTML Help installed then this call will crash your application. Here is safer code. Notice we are checking if HH is installed before calling HtmlHelp();

procedure HHCloseAll;
begin
   If @HH.HtmlHelp <> Nil then  //HH API is available
   begin
      HH.HtmlHelp(0, nil, HH_CLOSE_ALL, 0);
      Sleep(0); 
   end;
end;

 

VB and HTML Help

Getting access to the HTML Help API is fairly straightforward.
This document shows you how you do it in VB: Q244140.
Once you have access to the API you call htmlhelp() with the appropriate HH command.

Calling HH_CLOSE_ALL:

The example in Q244140 above is wrong. Always call HH_CLOSE_ALL as early as possible during shutdown. Form Query Unload is better than Form Unload. Form Unload will cause access violations on some machines. The problem is described in the section above. Not calling HH_CLOSE_ALL will causes an access violation if help is running on shutdown. Here is the code.

Private Sub Query_Unload(Cancel As Integer)
   Call HtmlHelp(Me.hWnd, "", HH_CLOSE_ALL, 0)
End Sub.

Examples of help calls:

' Opening a help topic by topic path
Call HtmlHelp(Me.hWnd, HelpFile, HH_DISPLAY_TOPIC, 0)

' Where HelpFile = App.Path & "\myfile.chm
' or App.Path & "\myfile.chm::/topic.htm
' or App.Path & "\myfile.chm::/topic.htm#bookmark

' Opening a help topic by Help Context ID 3099
Call HtmlHelp(Me.hWnd, App.Path & "\myfile.chm, HH_HELP_CONTEXT, 3099)

API Documentation:

The HH API documentation is part of HTML Help Workshop online help.
The Workshop Installer (htmlhelp.exe) can be downloaded free from 
http://msdn2.microsoft.com/en-us/library/ms670169.aspx

VB6 and WhatsThis Help:

Visual Basic 5 was written pre-HTML Help. It has no built-in support for HTML Help. VB6 does support HTML Help but has a some bugs. When you specify the help file you either specify a CHM file OR you elect to use WhatsThis help and specify a path like CHMfile::/popup.txt file. If you want to use WhatsThis help then you do the latter and use the HTML Help API for your non-WhatsThis help calls.

David Liske covers using WhatsThis help with VB6 nicely at:
http://www.mvps.org/htmlhelpcenter/whcomplete.htm

More Info:

 

Standard C++

To gain access to the HTML Help API, you link to the Htmlhelp.lib file and include the Htmlhelp.h file in your Windows program. Both of these files are installed on your system when you install HTML Help Workshop.

For more information read your Workshop help 
C++ Help:      its:c:\WINDOWS\Help\api.chm::/ov_accessing.htm
HH API Help:  its:c:\WINDOWS\Help\htmlhelp.chm::/apiref.htm

More Information:

  • Don Lammers site has some excellent tutorials:
      http://www.smountain.com/m_ProgrammingHelp.htm
     
  • Ralph Walden has C code to access file inside a CHM.

    CHM files are stored in what in techie-speak is called an IStorage format. That allows you to read any of the files within a CHM file without having to know the storage format. Source code for doing that is part of the source code package at keyworks.helpmvp.com/code/ (see the CItsFile class).

 

.NET (C++/C#/VB) and HTML Help

If you are a component writer for VS .NET or Borland C# Builder etc. you may want to write help in MS Help 2.x and integrate your help directly into the main help collection for tightest integration.

Standalone .NET applications you create use HTML Help 1.x by default. To display help via the .NET Framework Class library, invoke the Help.ShowHelp Method (System.Windows.Forms.Help object, a static class that encapsulates the HTML Help 1.x engine.).

The above method appears to be a high-level call (like the ShowHelp method we use in IE Script). Most developers however access help via HelpProviders. I'm getting out of my depth here so I will direct you to an excellent article written by Michaels Waltuch where he explains HelpProviders and other help related calls:

Borland Delphi and HH

Free code examples show you how to program the HTML Help API via Borland Delphi.

See the Delphi HH Kit  page

 

Borland C++ Builder and HTML Help

HTML Help can be opened through the System.Windows.Forms.Help object. This object is a static class that encapsulates the HTML Help 1.x engine. This class cannot be instantiated, and its methods must be called directly.

See the Delphi HH Kit  page
 

Calling Help from MS Office Apps

The following resources should be useful when it comes to hooking up your help file to an Office file.

Office 2000 - Adding Help to your Custom Solution:

Office 2000 - Creating your own Help Topics:

HelpAPI VBA Module:

 

Help and .NET Applications

See also MS Help 2 Info

HH_GET_LAST_ERROR

The HH_GET_LAST_ERROR command refers to a missing file Hherror.h which can be found in the following KB article.

http://support.microsoft.com/default.aspx?scid=kb;en-us;297768

The HtmlHelp.h file has a comment with HH_GET_LAST_ERROR that say "not implemented" however it appears it is at least partially implemented. If I call HtmlHelp(0, PChar(mHelpFile), HH_HELP_CONTEXT, 911); where 911 is an invalid ContextID, then HH_GET_LAST_ERROR  returned Error 0x8004020A with Description text "The compiled help (.chm) file does not contain context IDs."

For most types of errors HH_GET_LAST_ERROR appears to return 0x80004005 "Unspecified error".

 

Search From Application

HH Workshop API documents how to move to the search tab and initiate a search. Unfortunately the initiating a search part has always been broken in HH. The only way around this would be to find the HH window and search pane controls. Then control those controls from your application using via low level Windows API calls.

Dmitry Karpezo,
posted a small code example on MSHelp2 Yahoo group - Download Example Code, 
HTMLHelpQuerySample.zip

 

Help Window Control

If you open a help window using the Help API, the HTMLHelp() function returns the handle of the help window. This handle can be used to manipulate the help window using standard windows API calls. Here are a few functions to get you going:

f = IsZoomed(h); //returns true if window Maximized
f = IsIconic(h); //returns true if window Minimized
f = IsWindowVisible(h); //returns true if window showing
f = IsWindow(h); //returns true if the handle is still valid (false = user has closed window)

//Set window position and size window
SetWindowPos(h, ...., SWP_SHOWWINDOW);

//Set window state
ShowWindow(h, SW_RESTORE)
ShowWindow(h, SW_SHOWMINIMIZED)
ShowWindow(h, SW_SHOWMAXIMIZED)
ShowWindow(h, SW_HIDE);
ShowWindow(h, SW_SHOW);

 

KeyHelp Popups

KeyHelp is a free ActiveX control from keyworks.helpmvp.com A great way to extend HTML based help. It can be used in any environment that supports COM. We use it in some Delphi applications. The popup window (just one part of KeyHelp) uses an IE Browser control, so it can display anything an IE window can. And unlike the current lame CHM popups, KeyHelp can open and display any topic in your CHM.

Using KeyHelp Popups:

The trick to successfully using KeyHelp popups is to use a full path to the HTML filename you want to display. Relative paths will cause problems (well Da!). Here is a small example showing you how to expand a file name using JavaScript.

Other KeyHelp Info:

 

How does an Application open a Slave Topic?

Q. How can my application access a slave topic in a merged help system.

A. This is actually not as straightforward as it may seem.

    See Context IDs in Merged Help (2)

 


Translation Info

Compiling Japanese on a Win 2K/XP English PC

Problem:

When we compile our Japanese HTML Help project under Eng Win2K (with Japanese language pack installed), the resultant Japanese CHM looks fine, BUT... we cannot perform a search. Even if we move the CHM to a Japanese PC, the search still does not work.

In Win2K with its new Language support, shouldn't we be able to switch to Japanese and compile from there? If I compile on a pure Japanese PC the resultant Japanese CHM works fine on both my PCs.

Solution:

Marc Islam, from the MS Help development team, came back with this solution...

"You're absolutely right about Win2K and the compiler.  It *should* work.
And it does...  but not without a bit of work,  The compiler is not Unicode enabled.  As such, we rely on the system default language for our string manipulation/conversions.  If the system language is not set to JPN, then portions of the compilation will fail (full text search, keyword sorting, perhaps even the storage of localized topic titles that appear in the disambiguator).

To set the System default language to Japanese...

Windows 2K:

  1. Control Panel->Regional Options
  2. At the bottom, where you can check the different languages to support, click on Set Default...
  3. Select Japanese from the list
  4. Reboot, recompile, re-run the test case

Windows XP:

  1. Control Panel->Regional Options
  2. On the "Languages" page make sure make sure you check the box "Install files for East Asian languages".
  3. On the "Advanced" page select "Japanese" from the language dropdown list.
  4. Reboot, recompile, re-run the test case

Alternative Instructions: KB Article 324603

 

Japanese HTML Help Setup

Problem:

Why don't I see Japanese characters in my Japanese HTML Help?

Solution:

This description applies to all all language translations, however we will look a Japanese.

Use a Japanese Platform:

First off, compile on a Japanese Windows machine or  a Win2K/XP set up for Japanese (see above).

HTML Content:

To view HTML content correctly you will need to insert the appropriate Meta statement into the head section of each HTML file. This can be done very quickly using FAR find and replace. When you install or update Internet Explorer, make sure you install the Japanese language pack.  Remember that Internet Explorer is used to display HTML content in the HH window. Use "shift_jis" for Japanese. For other codes check the HH Workshop online help.

<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=shift_jis">
</head>

Example: If your IE is setup correctly the following page should display Japanese characters.  Do "View Source" on this web page to see the Meta statement in the head section: http://www.asahi-net.or.jp/service/guidance/freeaddr/index.htm

For other language codes see HH Workshop help: "Character Set Recognition"
    mk:@MSITStore:c:\WINDOWS\Help\htmlhelp.chm::/tagref/html0a0g.htm

HTML Help International Settings:

Set the correct HH project (.HHP) properties - Language and Char Set (Character Set).

HTML Help TOC Settings:

Set the correct TOC (.HHC) property - Char Set (Character Set).
For languages such as Russian, you will also have to set the TOC Font property. Example: Try Verdana, Arial or Times Roman.

HTML Help Index Settings:

Set the correct Index (.HHK) property - Char Set (Character Set).
For languages such as Russian, you will also have to set the Index Font property. Example: Try Verdana, Arial or Times Roman.

 

Unicode Support

Problem:

I have HTML files encoded as Unicode but HTML Help wont display them correctly in a compiled HH window. These files display fine uncompressed in the browser.

Solution:

HTML help does not support Unicode. The next version of help will.

According to KB Article Q269766 HTML Help version 1.3x can display Unicode-encoded content (by using the Microsoft Web Browser control). The use of different languages within the same topic is not supported, and can cause problems when using the table of contents and indexing features. The ability to index and search Unicode content is not currently supported, but this functionality is under consideration for future releases.

This KB is a little misleading. HH 1.x contains no support for Unicode. However the embedded IE browser in the HH Window can display Unicode HTML.

If you add the correct encoding header to your Unicode HTML files, and save them to the UTF-8 flavour of Unicode it should display OK in the browser. However for non-English languages you will find that the Search and Index and TOC will have problems.

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Test</title>
</head>

Rob: Testing this under WinXP (HH1.33), Win2K(HH1.30) -- I had no trouble with the Index and Full-text search features of HH (UTF-8). However I was testing this with English.

 

Extra Thoughts:

The HH Compiler appears to flattens UNICODE and UTF-8 files to ANSI-MultiByte but the file lead signature bytes are not removed (we are talking files stored inside CHM). This means that when the HH Browser control tries to display the (now flattened) UNICODE file, it displays junk characters.

The UTF-8 survives much better. The conversion to ANSI-Multibyte leaves it mostly untouched, and those special characters that are pure 2,3,4,5 byte UTF-8 survive OK for me (seem untouched). If the author is only using English text, then the parser will work fine and only the special characters (maths symbols etc) wont be parsed correctly.

 

Compile different Locales without Rebooting

Normally to compile HH projects of different languages you need to set the windows codepage and reboot (see above). This is because HTML Help is an ANSI application built in the dim dark ages of Win 95 time frame. HH Workshop and HHC.exe cannot correctly read your ANSI HTML files, and parse  and sort them correctly unless region settings (control panel) is correctly set to the matching codepage.

However, Anand of the Sandcastle team posted some interesting tips on how to compile under different locales without rebooting Windows.

Anand: "Wrap the call to HHC.exe in a call to MS APPLocale or SbAppLocale.exe, passing in the appropriate LCID."

 

http://blogs.msdn.com/b/sandcastle/archive/2007/09/29/chm-localization-and-unicode-issues-dbcsfix-exe.aspx

 


Other Help Info

Help and Support Center

What is Help and Support Center?

Under Windows XP & Server 2003, minimize all running applications and press F1. The Help & Support Center window will appear.

HSC is an attempt at consolidating the help and support resources of different providers (ISVs, OEMs, Microsoft etc), into a single place in Windows. The help can come from a variety of sources: HTML Help, HTML files, PDF, PostScript etc. HCS can retrieve help from local help files or from remote locations.

I believe a version of HSC first appeared in WinME. HSC is part of Windows and can not be installed on other Operating Systems.

Can I add content to HSC?

Yes at the moment both ISVs and OEMs can integrate content into HSC, participate in Keyword search etc. OEMs have customization privileges.

What can ISVs do?

ISVs (Independent Software Vendors) must obtain a Class-3 code signing certificate to digitally sign update packages; Can install the production tool that creates the update packages; Can distribute packages.

What can OEMs do?

OEMs can go a step further. They can customize the interface; Extend the taxonomy (content); Participate in the index; Add to the extensible search; Use the headlines; Link to an e-support application.

More information

Interested in finding out more information. Please write to hscisv@microsoft.com.

See also:

 

Script Tips
  • Remove IE window.Close() message - From Guru Rick Stone (23-Mar-2003)

window.close(); causes an IE message advising that the script is trying to close the window. The following code from Rick fixes this:

<a href="" onClick="var pw=window.parent;pw.opener=window.self;pw.close();">
Close Window</a>

 

WinHelp to HTML Help

This is often a job you have to do once. You convert your WinHelp files and then work in HTML Help from then on. When I did my ports to HTML Help I borrowed a copy of RoboHelp which did an excellent job. I don't particularly like RH but this conversion part saved me a lot of time and energy.

You can also use HH Workshop (free from MS) to convert WinHelp projects into HTML Help. Here's some good news from Sid who has written a free utility to unscramble the names after conversion using workshop.

I am working mostly on converting some big Winhelp projects to HTML Help. 
I have written some notes on problems that I encountered - might be useful 
to others that are doing conversions. They are at:
http://post.queensu.ca/~penstone/notes_on_fixing_html_help.html

I also wrote a little utility HHPMod to restore the .htm file names 
scrambled by HTML Workshop, and to rewrite the alias and map files from the old WinHelp to work with the HTML project:
http://post.queensu.ca/~penstone/HHPMod/HHPMod_info.html

-- 
Sid P.


 

Subpages (1): Non-English HTML Help
ċ
demo_ext2.zip
(54k)
Robert Chandler,
12 May 2012, 01:48
Comments