This article first appeared in PC TECHNIQUES, Feb/Mar 1993
Download the listings for this article (guide.zip, 17KB)
If you've worked much with Windows, you've likely noticed that most Windows programs include online documentation--normally accessed via the application's Help menu. The help files contain hypertext links, popup topics, browse sequences, and a keyword search capability. All of these basic features (and much more) are provided by the Windows help engine, WINHELP.EXE. This article explains how to make the basic help features available from your programs.
With the exception of context-sensitive help, all of the WINHELP features are program independent, and the trick to accessing them lies in the construction of the help resource file (.HLP extension). Interfacing with the help system from your application is relatively simple, as you will see.
The Windows Help Compiler (HC.EXE) reads the help project and topic files that you create, and generates the help resource file, which WINHELP can then display. Figure 1 illustrates this sequence of events.
The help topic file (also called an RTF file) is an ASCII text file that contains text and Rich Text Format (RTF) commands. These files can be created manually by inserting the proper commands into a text file, or by a word processor such as Microsoft Word, which is capable of reading and writing RTF files. There are also commercial and shareware programs that will convert other word processor formats to Rich Text Format. TESTHELP.RTF (Listing 1) is an example of a help topic file in RTF format.
The entire contents of the topic file must be enclosed in braces ({ }), and the first statement in the file must be the \rtf1 statement. This statement should be followed by a character set selection statement and the \deff statement, which defines the default character font. The most common character set used is ANSI, which is selected by entering the \ansi statement. The first line of most help topic files, then, is:
{\rtf1\ansi\deff0
The only other required initialization within the topic file is the font table, which typically contains a half dozen or so fonts, but can contain as many (or as few) as you like. The help system is capable of displaying any installed font. However, if your program is going to be distributed to many different systems, you should use only those fonts that are shipped with Windows. TESTHELP.RTF makes use of 4 fonts: Courier, Arial, Tms Rmn, and Symbol.
With the required initialization out of the way, we can start adding information to our help file. We'll start with a discussion of topics.
With the exception of the initialization section that we just covered, a help file is composed of individual topics--distinct units of information such as a contents screen, a popup definition, a list of instructions, etc. The help system can display only one topic at a time, but a user can view different topics by selecting hot links to other topics, or by searching on defined keywords. Building the help file consists of creating the text for each topic and defining hotlinks, browse sequences, and search keywords.
A topic definition begins with one or more \footnote statements, and ends with a \page statement. All of the text and statements that fall between the first \footnote statement and the \page are part of the topic. The \footnote statement is most commonly used to identify topics, and also to assign titles, browse sequences, and search keywords. Every topic must have a context string; a unique name that is used to identify this topic within the help file. All other footnote entries are optional. A footnote entry takes this form:
n{\footnote text}
where n is one of the footnote characters described in Table 1, and text is dependent on the footnote character. In this article, we will cover only the four most common footnote types. For information on the other footnote types, refer to the sources noted at the end of the article.
* | Build tag | Used in conjunction with the BUILD option and the [BUILDTAGS] section of the help project file. |
# | Context string | The text parameter can contain letters and/or digits, but may not contain spaces. Letters are case-insensitive in context strings. This is the name by which other topics refer to this topic. |
$ | Topic title | This title is used by Windows Help to identify the topic in Search and History dialog boxes. The text parameter may contain any characters, including spaces. |
+ | Browse sequence identifier | Used in conjunction with the browse buttons to access topics in hierarchical order. The text parameter is a combination of letters and/or digits and may include an optional sequence number. |
K | Keyword | Specifies the word or words that Windows Help uses to refer to the topic in the Search dialog box. The text parameter may contain any combination of characters. If the first character is the letter K, it must be preceded with an extra space or a semicolon. |
! | Help macro | Windows help executes the macro when the topic is displayed. The text parameter can be any help macro. |
The context string (# footnote) must be the first footnote entry for a topic, and each topic can have only one context string. A topic must have a context string if it is going to be referenced by either the help system (via hypertext links or search keywords), or by the application program (via help context numbers). The context string may contain any combination of letters and digits, and the underline character (_). Context strings are case-insensitive--C programmers take note!
Browse sequences (+ footnote) allow the user to quickly page through a sequence of related topics in sequential order. For example, in a program that contains several menus, the user may want to view information about the File menu, followed by the Edit, Search, and other menus, in the order that the menus appear in the application.
The text parameter for this footnote entry is the topic's browse sequence identifier. A browse sequence identifier consists of two parts: an identifier and an optional sequence number. For all but the most rudimentary help files, you'll want to use sequence numbers to specify the browse order, and to create multiple browse sequences. The help topic file in Listing 1 contains 1 browse sequence with the title Index, and the browse order is:
Contents (Index:0005) FontExamples (Index:0050)
Chars (Index:0150) Formatting (Index:1250)
FileMenu (Index:2500)
Notice that the sequence numbers all the same number of digits. Because the help compiler sorts browse sequence identifiers alphabetically (rather than numerically), leading zeros are required in order to maintain proper ordering. If the leading zeros were removed from the sequence numbers, the help compiler would order the browse sequence like this:
Formatting Index:1250) Chars (Index:150)
FileMenu (Index:2500) Contents (Index:5)
FontExamples (Index:50)
Windows Help provides a Search facility through which users can select a keyword and choose to view topics that are associated with that keyword. The interface for this mechanism is the search keyword (K) footnote entry.
The text parameter for the keyword footnote contains the topic's search keywords. The search keywords may contain any combination of characters, including spaces. Multiple search keywords within the footnote statement must be separated by semicolons. If the first letter of the search keyword is 'K', then an extra space must be placed between the \footnote statement and the first letter of the keyword.
Search keywords are displayed in a dialog box when the user selects the Search button. Once the user selects a search keyword, the topic titles that correspond to that keyword will be displayed. The user can then select a topic for viewing.
The text parameter for the topic title ($) footnote entry contains the topic's title, which is displayed by the Search and History dialog boxes. The topic title may contain any combination of characters, including spaces. The Search and History dialog boxes will display >>Untitled Topic<< for all topics that do not have titles. In addition, the help compiler will generate a warning if it encounters a topic that has search keywords defined, but no title. It's a good idea to title all topics.
Everything between the \footnote statements that open a topic and the \page statement that closes a topic is considered topic text. This is the information that is displayed when the user selects a topic, and consists of text and text-formatting commands. The help compiler supports a wide range of text-formatting commands--too many to cover in one short article. We will touch on only the most basic of these commands.
Earlier, we discussed the \fonttbl entry which defines the fonts that are used within the help file. In addition, I pointed out that the \deff statement defines the default font. If you wish to display text in a font or size other than the default, you must specify the new font or size with the \f or \fs statement. The FontExamples topic on line 16 of Listing 1 shows how to use different fonts within the help file.
The \fs statement defines the character size in half points. So, if you want to display 10-point text, you would specify \fs20. If no \fs statement is given, the default font size is 12 points.
You'll notice in the FontExamples topic that the \f and \fs statements and the text that is affected by them are enclosed in braces. This is to eliminate the need to explicitly switch back to the previous font or font size. Braces limit the scope of a character property to just the enclosed text. This is true of all character properties, including \fs, \b, \ul, \uldb, and \v.
The \plain statement resets all character properties to defaults: bold, italic, and small caps are turned off, the font is reset 0, and the font size is set to 24.
Several character properties can be added to highlight specific portions of text. And, as you would expect, multiple properties can be assigned to text so that you can have bold italic text, for example. The Character Properties topic in Listing 1 gives examples of character properties. As mentioned previously, enclosing a character property in braces limits the scope of that property to just the enclosed text. In addition, the \plain statement resets the bold, italic, and small caps properties.
All of the statements that turn character properties on have corresponding "off" statements. For example, to turn bold off, you can include a \b0 statement within your text. This is a handy feature if you want to turn a property off for just a small section of text. For example, the word "not" in the text below would not be italicized:
{\i One word in this sentence is \i0 not\i italicized.}
Within a topic, text is composed of paragraphs, which are separated by \par statements. When entering your text into the RTF file, you need not worry about margins--Windows help handles wrapping text that is too long to fit within the help window. When the help window is resized, the text will be automatically reformat to fit within the horizontal boundaries of the window.
If you don't want the help system to automatically format your text, precede the paragraph with the \keep statement. The \keep statement will remain in effect until a \pard statement is read, and will prevent Windows help from wrapping your text. The help compiler ignores carriage return/line feed pairs in the source help file, so you must separate lines in your text with \line statements. The \keep statement is especially useful for displaying program source code.
Be advised, though, that the \pard statement affects the entire paragraph that it is found in. So, if you put a \pard somewhere within a paragraph, the \keep statement at the beginning of the paragraph will be canceled. Place the \pard statement at the end of the paragraph, after the \par statement that marks the end of the paragraph.
The Formatting topic in Listing 1 contains examples of paragraph and line formatting.
This is what it's all about. Hypertext links are one of the major features of Windows help. And they're easy to create. Once you've created the topics and topic text, building a hypertext link is a simple matter of assigning a character property to the link and telling the help compiler which topic is to be linked to the text. The help compiler documentation calls these "hot spots".
There are two kinds of hypertext links: jumps and popups. Jumps take the user to a completely different topic, and are normally used for contents screens and longer explanations. Popups display an information box on top of the current topic, and are normally used for definitions and other text that is relatively short.
A jump link is created by assigning the \uldb property to a portion of text, and following it with a \v statement. The parameter to the \v statement is the context string for the topic that will be viewed if the mouse is clicked on this hotspot. Popup links are created by assigning the \ul property to a portion of text, and following it with a \v statement. The Contents topic in Listing 1 contains examples of jump and popup links.
The help project file contains filenames, options, and other information that the help compiler uses in order to construct the help resource file from the help topic files. This file must be an ASCII file and must have the .HPJ extension. The name of this file is the single command-line parameter to the HC.EXE program.
There are 9 sections in a help project file, most of which are optional. Within each section, there are many options that can be specified. In this article, we will cover only the four basic sections that are required to build all but the most rudimentary help files.
The OPTIONS section is optional, but in my opinion very necessary. If used, it should be the first entry in the help project file so that the options are active during the entire build process. TESTHELP.HPJ (Listing 2) uses several of the options, but there are many others. See the references at the end of the article for information on the other [OPTIONS] entries.
The FILES section, which is required, specifies which files are to be included in the build. You can specify full or partial pathnames of the files. If a partial pathname is specified, the help compiler will search the directories specified by the ROOT option in the OPTIONS section.
The optional CONFIG section contains one or more macros that carry out specific actions such as enabling the browse buttons, or registering DLLs with the help system. Any help file that makes use of browse sequences must include a BrowseButtons() macro invocation in this section.
In order to provide context-sensitive help, a context number, which identifies the topic to be displayed, is passed to Windows Help by the application program. The optional MAP section in the help project file assigns context numbers to their corresponding context strings.
There are three forms you can use to assign context numbers. Two methods are shown in Listing 2. The third method is to put all of the context identifiers in a separate file and use the #include directive to load them into the MAP section. This method is especially useful when a writing a C program because the C program and the help project file can use the same file of context identifiers.
Once you've created the help resource file and added the help context identifiers to the MAP section of your help project file, you're ready to add context-sensitive help support to your programs. The mechanism that makes this possible is the WinHelp Windows API function:
Function WinHelp (Wnd : HWnd; HelpFile : PChar; Command: Word; Data : LongInt) : Bool;
Wnd is the handle of the window that's invoking the help mechanism, and HelpFile is the name of the help file that is to be loaded. Normally, these two parameters will remain the same for all WinHelp calls within a given program. It is the other two parameters that determine what the help system actually does once it is invoked.
The Command parameter must be one of the help constants shown in Table 2, and the Data parameter is dependent upon the Command parameter. The most common commands, and the only ones used by the example program are: Help_Contents, Help_Context, Help_HelpOnHelp, and Help_Quit.
Help_Context | Displays Help for a particular topic identified by a context number that has been defined in the [MAP] section of the .HPJ file. The Data parameter must be a long integer containing the context number for the topic to be displayed. |
Help_Contents | Displays the Help contents topic as defined by the Contents option in the [OPTIONS] section of the .HPJ file. The Data parameter is ignored and should be set to 0. |
Help_SetContents | Determines which Contents topic Help should display when a user presses the F1 key. The Data parameter must be a long integer containing the context number for the topic the application wants to designate as the Contents topic. |
Help_ContextPopup | Displays in a pop-up window a particular Help topic identified by a context number that has been defined in the [MAP] section of the .HPJ file. The Data parameter must be a long integer containing the context number for the topic to be displayed. |
Help_Key | Performs a keyword search on the string passed in the Data parameter. If one topic is found, that topic is displayed. If more than one topic is found, the Search dialog box is displayed with the topics listed in the Go To list box. The Data parameter is a PChar pointer to a string that contains a keyword for the desired topic. |
Help_PartialKey | Performs a keyword search on the string passed in the Data parameter. If one topic is found that exactly matches the passed keyword, that topic is displayed. If there is more than one match, the Search dialog box is displayed with the topics listed in the Go To list box. If there is no match, the Search dialog box is displayed. The Data parameter is a PChar pointer to a string that contains a keyword for the desired topic. If you just want to bring up the Search dialog box, you should use a long pointer to an empty string (i.e. PChar ('')). |
Help_MultiKey |
Displays the Help topic identified by a keyword in an alternate key word table. The Data parameter is a pointer A long pointer to the TMultiKeyHelp structure. |
Help_Command | Executes a help macro. The Data parameter is a PChar pointer to a string that contains a Help macro to be executed. |
Help_SetWinPos | Displays the Help window if it is minimized or in memory, and positions it according to the data passed. The Data parameter is a pointer to the THelpWinInfo structure. |
Help_ForceFile | Ensures that WinHelp is displaying the correct Help file. If the correct Help file is currently displayed, there is no action. If the incorrect Help file is displayed, WinHelp opens the correct file. The Data parameter is ignored, and should be set to 0. |
Help_HelpOnHelp | Displays the Contents topic of the designated Using Help file (normally WINHELP.HLP). The Data parameter is ignored and should be set to 0. |
Help_Quit | Informs the Help application that Help is no longer needed. If no other applications have asked for Help, Windows closes the Help application. The Data parameter is ignored and should be set to 0. |
TESTHELP.PAS (Listing 3) is just a program shell that illustrates how the help system is accessed from a program. The Contents topic of the help file can be displayed by pressing the F1 key.
The bulk of the code that makes up TESTHELP.PAS is concerned with properly maintaining and handling the help cursor. When the user presses Shift+F1, the Help flag in the THelpWin object is set to True, and a question mark is added to the cursor. When the left mouse button is pressed, WinHelp is invoked to display information about the particular topic that was clicked on. The THelpWin.WMKeyDown method handles the F1 and Shift+F1 keys, and the WMLButtonDown, WMCommand, and WMNCLButtonDown methods take care of calling WinHelp if the mouse is clicked on an item when the THelpWin.Help flag is set to True. The rest of the code is fairly standard OWL stuff that's required by any program.
In order to build the help file and the test program, you must first start Borland's Resource Workshop and compile the TESTHELP.RC (Listing 4) resource script. The Microsoft Resource Compiler (RC.EXE) will not be able to compile this script. Save the compiled resource file as TESTHELP.RES. Then, compile the help file by executing this command at the DOS command prompt (or by entering the command at the Program Manager File|Run prompt):
hc testhelp
Finally, compile the TESTHELP.PAS program by executing this command:
bpc testhelp
There is much more to RTF files and Windows Help than I can present in this article. We covered only the very basic RTF formatting commands, completely ignored the use of bitmaps and help macros, and skipped more than half of the WinHelp API.
What I have presented, though, will enable you to add basic help capabilities to your Windows applications, and should point you in the right direction if you wish to add even more featuresto your help files.
In addition to the Help Compiler documentation that came with your development system, I recommend the following materials for further study:
Microsoft Corporation [1992]. Microsoft Windows 3.1 Programming Tools, Microsoft Press, Redmond, WA.
Microsoft Corporation [1992]. Microsoft Windows 3.1 Programmer's Reference: Volume 4 Resources, Microsoft Press, Redmond, WA.