HTML Help - Creating What's This Help

Created: 9-Aug-02003, by Rob Chandler, MS Help MVP

What's This Help (also know as application popup help) is the field level popup help that appears when the F1 key is pressed. Applications also provide popup help via a [?] button in the title bar. This document discusses how to create What's This help.

Do You Really Need Field Level Help?

Field level help can be very costly to write and maintain.

The help author must write separate help for every control in the application, and the developer must assign a unique Integer ID for every control requiring help. The evaluation effort can be enormous for large applications given that every help link must be tested.

These days most companies provide page or dialog level help. Pressing F1 or clicking the Help button displays a help window containing help for the current page or dialog. But there are still many popular applications (such as MS Office) which still provide field level popup help.

Consider also that What's This help may not suite all applications. Focusing all help assistance on a particular field may not be appropriate.

That said lets now continue with Creating What's This Help for MS HTML Help.

Which Popup? - WinHelp, HTML Help or KeyHelp

WinHelp

In the beginning there was WinHelp providing excellent rich popups. In the early days of HTML Help the humble HH popup was fairly lame, and even Microsoft themselves continued to use WinHelp popups for sometime. Mixing WinHelp rich popups with HTML Help is still an option, however I hope you will be convinced otherwise shortly.

HTML Help

HTML Help (introduced in 1997 with IE4) initially provides a fairly lame text popup, again read from the help file. A later release (HH Version 1.2?) also allowed you to provide text directly or from a resource string, as well as the ability to set the popup's color and margins. HH popups are plain text only.

KeyHelp

KeyHelp is a free ActiveX control from Keyworks.net and providing beautiful rich HTML popups. KeyHelp was developed by Ralph Walden and Cheryl Lockett Zubak. Ralph is x-Microsoft and was heavily involved in the development of WinHelp and HTML Help during his many years at Microsoft. This is the best choice for displaying rich popups.

KeyHelp Popups

Lets first look at coding for KeyHelp (by keyWorks) which is the best way to provide rich popups. Keyhelp works in any environment that supports ActiveX. So it works on the application side or in a HTML help topic file using javascript or vbscript. KeyHelp provides two popup related methods.

IKeyPopup::DisplayMapID(1500, 'c:\test\mytest.chm', X, Y);
    displays a popup with Context ID = 1500 at position X,Y.

IKeyPopup::DisplayURL('c:\test\mytest.chm::/index.htm', P.X, P.Y);
    displays a help topic index.htm as a popup at position X,Y.

Application Side Code

Here is a snippet of Delphi code. Other languages will be similar.

//IKeyPopup interface is used to display an HTML page in a popup window.
var _IKeyPopup: Variant;
try
  _IKeyPopup := CreateOleObject('KeyHelp.KeyPopup');
  //Display .CHM file topic index.htm in a keyhelp popup
  _IKeyPopup.DisplayURL('c:\test\mytest.chm::/index.htm', 100, 100);
except
  ShowMessage('Error connecting to IKeyPopup. Is KeyHelp.Ocx registered?');
end;
VarClear(_IKeyPopup);  //done with object

Help Side Code

Here is some sample script taken from KeyScript.js which comes with the KeyHelp download (you may need to decompile the CHM file to get it).

<script language="javascript">
  // copyright (C) 1999-2000, Work Write, Inc.
  // and KeyWorks Software. All rights reserved.
  // Contact: Cheryl Lockett Zubak at cheri@workwrite.com

var KeyPopup; // KeyHelp.KeyPopup ActiveX object
function KeyDisplayPopup(ULR,left,top) {
  if (!KeyPopup) 
     KeyPopup = new ActiveXObject("KeyHelp.KeyPopup");
  KeyPopup.DisplayURL(ULR, left, top);
}
</script>

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

Defining Popup Text in a CHM

There are two HH API popup commands, both can display text stored in a CHM help file. This section provides an example of how to define popup text in a .CHM help file.

First create a text file called cshelp.txt:

<cshelp.txt>

.Topic 99
 This is my test popup text with ID=99
 The source lives in "help.chm::/cshelp.txt"

.Topic IDH_POPUP_NEWBTN
 Click New to create a new file.

.Topic IDH_POPUP_OPENBTN
 Click Open to open an existing file.

You can write the context ID number directly into the text file as seen above with Topic 99.  Or you can define identifiers in a separate C++ header file as done with the other 2 declarations.

<file: cshelp.h>

 #define IDH_POPUP_NEWBTN        61
 #define IDH_POPUP_OPENBTN       62

Lastly we need to add the following lines to our help project (.hhp) file and compile it to a CHM file.

...
[MAP]
 #include cshelp.h

 [TEXT POPUPS]
 cshelp.h
 cshelp.txt
 [FILES]
 cshelp.h
 cshelp.txt

Notice I also added cshelp.h and cshelp.txt to the [FILES] section to ensure that the files are definitely compiled into the target .CHM help file.

 

HTML Help API Commands

The HTML Help API provides the application with two popup commands:

Documentation for the HH API calls, including C++ code, can be found in the HTML Help Workshop online help. Examples below are written in Delphi.

API Command: HH_TP_HELP_CONTEXTMENU

We pass an array of DWords containing control handle and topic ID pairs, terminated by two trailing zeros. The API call HtmlHelp() specifies the handle of the control that you are requesting help for, and the path to the popup text definition file (see previous section). The API will look up the relevant popup text in the CHM file using the popup ID, and display the popup over the control.

var dwIDs: array[0..3] of DWord; 

dwIDs[0] := ShowHHPopupBtn.Handle;
dwIDs[1] := 99;
dwIDs[2] := 0;
dwIDs[3] := 0;

HtmlHelp(ShowHHPopupBtn.Handle, PChar(‘c:\test\help.chm::/cshelp.txt'),
HH_TP_HELP_CONTEXTMENU, DWORD(@dwIDs[0]));

API Command: HH_DISPLAY_TEXT_POPUP

The HH_DISPLAY_TEXT_POPUP command offers more flexibility. You can set the popup color and popup margins. The popup text can be specified in three different ways: as an explicit text string, as resource string ID and as a popup ID representing a popup defined in a .CHM help file (see previous section).

We simply fill in a THHPopup structure and make the call.

Displaying a popup using supplied text:

{Show HH Popup using supplied text}
function HH_ShowPopupHelp1(aParent: TForm; Text: String; XYPos: TPoint): HWND;
var hhpopup: HH.THHPopup;
begin
  with hhpopup do
  begin
    cbStruct := sizeof(hhpopup); //sizeof this structure
    hinst := 0; //instance handle if str res
    idString := 0; //zero, resource ID, or topic ID
    pszText := PChar(Text); //text to display if idString=0
    pt := XYPos; //top center of popup 
    clrForeground := COLORREF(-1); //use -1 for default - RGB value
    clrBackground := COLORREF(-1); //use -1 for default - RGB value
    rcMargins := Rect(-1,-1,-1,-1);//amount of space between edges 
    pszFont := ''; //font
  end;
  Result := HtmlHelp(aParent.Handle, nil, HH_DISPLAY_TEXT_POPUP, DWORD(@hhpopup));
end;

In the HH_ShowPopupHelp1() example above, function parameter aParent is the form that will parent the popup, Text is the text string to display and XYPos holds the x-y coordinates for the popup. 


Displaying a popup using a string resource ID:

{Show HH Popup using a string resource} 
function HH_ShowPopupHelp2(aParent: TForm; resID: Integer; XYPos: TPoint): HWND;
var hhpopup: HH.THHPopup;
begin
  with hhpopup do
  begin
    cbStruct := sizeof(hhpopup); //sizeof this structure
    hinst := hInstance; //instance handle if str res
    idString := resID; //zero, resource ID, or topic ID
    pszText := nil; //text to display if idString=0
    pt := XYPos; // top center of popup 
    clrForeground := COLORREF(-1); //use -1 for default - RGB value
    clrBackground := COLORREF(-1); //use -1 for default - RGB value
    rcMargins := Rect(-1,-1,-1,-1);//amount of space between edges 
    pszFont := ''; //font
  end;
  Result := HtmlHelp(aParent.Handle, nil, 
  HH_DISPLAY_TEXT_POPUP, DWORD(@hhpopup));
end;

To display a text string based on a resource ID (above) we simply assign hinst=hInstance and idString=resID. For more information on how to store resource strings in an application see your compiler's manual.


Displaying a popup using text defined in a .CHM file:

{Show HH Popup using a string (StringID) from text file in a CHM
StringID: eg. 99; CHMTextFile: eg. _runDir + 'help.chm::/cshelp.txt'}
function HH_ShowPopupHelp3(aParent: TForm; StringID: Integer; 
  CHMTextFile: String; XYPos: TPoint): HWND;
var hhpopup: HH.THHPopup;
begin
  with hhpopup do
  begin
    cbStruct := sizeof(hhpopup); //sizeof this structure
    hinst := 0; //no used 
    idString := StringID; //topic number in a text file.
    pszText := nil; //no used
    pt := XYPos; //top center of popup
    clrForeground := COLORREF(-1); //use -1 for default - RGB value
    clrBackground := COLORREF(-1); //use -1 for default - RGB value
    rcMargins := Rect(-1,-1,-1,-1);//amount of space between edges
    pszFont := ''; 
  end;
  Result := HtmlHelp(aParent.Handle, PChar(CHMTextFile), 
  HH_DISPLAY_TEXT_POPUP, DWORD(@hhpopup));
end;

Finally the third and last example (above) tells the API to grab the popup text defined in a chm. This is much the same as the HH_TP_HELP_CONTEXTMENU example. Notice the second parameter is now defined as the path to the topic text file in the chm.


Color Parameter:

Just to wrap up the HH_DISPLAY_TEXT_POPUP popup discussion. The color parameters are either –1 for the default color or an RGB value. The easiest way is to specify a color is to use a three byte hexadecimal number where each byte represents a Blue, a Green and a Red value, $00BBGGRR.

Example of red text:
clrForeground := COLORREF($000000FF);

Example of blue text:
clrForeground := COLORREF($00FF0000);


Font Parameter:

The pszFont parameter allows you to specify a font. Use an empty string for the default font or specify ‘facename, point size, char set, BOLD ITALIC UNDERLINE’. You can leave a parameter blank to specify that the default value should be used.

Example: Char set is not specified so the default charset will be used:
pszFont := 'MS Sans Serif, 10, , BOLD';

More help on popups can be found in the API reference in Workshop online help.

Creating a What's This [?] button

Most applications will also require a “What’s This” toolbar button and help menu item.

In Delphi we need to enable the "What's This" Help_ContextPopup messages (these appear in the OnHelp event) by setting the form property BorderIcons := BorderIcons + [biHelp]; Do this in the FormCreate() or Object Inspector. Note that the What's This button in the title bar will not show if you have a minimize or maximize button. But you can make a toolbar button or menu item behave like a What's This button.

To accomplish this, call the following code. Here is my “What’s This” toolbar button click event code.

procedure TForm1.WhatsThisToolButtonClick(Sender: TObject);
begin
  DefWindowProc(handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
end;

Where handle is the current windows handle.

Note: Each Delphi window needs BorderIcons := BorderIcons + [biHelp] if you want the OnHelp event to correctly catch the What's this help event. For Delphi 6 and above OnHelp events do not fire correctly unless you have our free OnHelpFix Unit.