| Tenouk C & C++ | MFC Home | Context-Sensitive Help 1 | Context-Sensitive Help 3 | Download | Site Index |


 

 

 

 

 

 

 

 

Module 15a:

Context-Sensitive Help 2

 

 

 

 

 

 

 

 

 

 

 

 

This is a continuation from previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

  1. An Improved Table of Contents

  2. The Application Framework and WinHelp

  3. Calling WinHelp

  4. Using Search Strings

  5. Calling WinHelp from the Application's Menu

  6. Help Context Aliases

  7. Determining the Help Context

  8. F1 Help

  9. Shift-F1 Help

  10. Message Box Help: The AfxMessageBox() Function

  11. Generic Help

 

 

 An Improved Table of Contents

 

You've been looking at the "old-style" help table of contents. The latest Win32 version of WinHelp can give you a modern tree-view table of contents. All you need is a text file with a CNT extension. Add a new file, Simple.cnt, in the \mfcproject\mymfc22 directory, containing this text:

 

:Base Simple.hlp

1 Help topics

2 Topic 1=HID_TOPIC1

2 Topic 2=HID_TOPIC2

2 Topic 3=HID_TOPIC3

 

 

Creating Simple.cnt, a better WinHelp.

 

Figure 13: Creating Simple.cnt, a better WinHelp.

 

Notice the context IDs that match the help file. The next time you run WinHelp with the Simple.hlp file, you'll see a new contents screen similar to the one shown here.

 

A better WinHelp version.

 

Figure 14: A better WinHelp version.

 

You can also use HCRTF.EXE to edit CNT files. The CNT file is independent of the HPJ file and the RTF files. If you update your RTF files, you must make corresponding changes in your CNT file.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The Application Framework and WinHelp

 

You've seen WinHelp running as a stand-alone program. The application framework and WinHelp cooperate to give you context-sensitive help. Here are some of the main elements:

 

  1. You select the Context-Sensitive Help option when you run AppWizard.

  2. AppWizard generates a Help Topics item on your application's Help menu, and it creates one or more generic RTF files together with an HPJ file and a batch file that runs the Help Compiler.

  3. AppWizard inserts a keyboard accelerator for the F1 key, and it maps the F1 key and the Help Topics menu item to member functions in the main frame window object.

  4. When your program runs, it calls WinHelp when the user presses F1 or chooses the Help Topics menu item, passing a context ID that determines which help topic is displayed.

 

You now need to understand how WinHelp is called from another application and how your application generates context IDs for WinHelp.

 

Calling WinHelp

 

The CWinApp member function WinHelp activates WinHelp from within your application. If you look up WinHelp in the online documentation, you'll see a long list of actions that the optional second parameter controls. Ignore the second parameter and pretend that WinHelp has only one unsigned long integer parameter, dwData. This parameter corresponds to a help topic. Suppose that the SIMPLE help file is available and that your program contains the statement:

 

AfxGetApp()->WinHelp(HID_TOPIC1);

 

When the statement is executed in response to the F1 key or some other event the Help Topic 1 screen appears, as it would if the user had clicked on Topic 1 in the Help Table Of Contents screen.

 

"Wait a minute," you say. "How does WinHelp know which help file to use?" The name of the help file matches the application name. If the executable program name is Simple.exe, the help file is named Simple.hlp.

 

You can force WinHelp to use a different help file by setting the CWinApp data member m_pszHelpFilePath.

 

"And how does WinHelp match the program constant HID_TOPIC1 to the help file's context ID?" you ask. The help project file must contain a MAP section that maps context IDs to numbers. If your application's resource.h file defines HID_TOPIC1 as 101, the Simple.hpj MAP section looks like this:

 

[MAP]

HID_TOPIC1        101

 

The program's #define constant name doesn't have to match the help context ID; only the numbers must match. Making the names correspond, however, is good practice.

 

Using Search Strings

 

For a text-based application, you might need help based on a keyword rather than a numeric context ID. In that case, use the WinHelp HELP_KEY or HELP_PARTIALKEY option as follows:

 

CString string("find this string");

AfxGetApp()->WinHelp((DWORD) (LPCSTR) string, HELP_KEY);

 

The double cast for string is necessary because the first WinHelp parameter is multipurpose; its meaning depends on the value of the second parameter.

 

Calling WinHelp from the Application's Menu

 

AppWizard generates a Help Topics option on the Help menu, and it maps that option to CWnd::OnHelpFinder in the main frame window, which calls WinHelp this way:

 

AfxGetApp()->WinHelp(0L, HELP_FINDER);

 

With this call, WinHelp displays the Help Table Of Contents screen, and the user can navigate the help file through jumps and searches. If you want the old-style table of contents, call WinHelp this way instead:

 

AfxGetApp()->WinHelp(0L, HELP_INDEX);

 

And if you want a "help on help" item, make this call:

 

AfxGetApp()->WinHelp(0L, HELP_HELPONHELP);

 

Help Context Aliases

 

The ALIAS section of the HPJ file allows you to equate one context ID with another. Suppose your HPJ file contained the following statements:

 

[ALIAS]

HID_TOPIC1 = HID_GETTING_STARTED

 

[MAP]

HID_TOPIC1        101

 

Your RTF files could use HID_TOPIC1 and HID_GETTING_STARTED interchangeably. Both would be mapped to the help context 101 as generated by your application.

 

Determining the Help Context

 

You now have enough information to add a simple context-sensitive help system to an MFC program. You define F1 (the standard MFC library Help key) as a keyboard accelerator, and then you write a command handler that maps the program's help context to a WinHelp parameter. You could invent your own method for mapping the program state to a context ID, but why not take advantage of the system that's already built into the application framework? The application framework determines the help context based on the ID of the active program element. These identified program elements include menu commands, frame windows, dialog windows, message boxes, and control bars. For example, a menu item might be identified as ID_EDIT_CLEAR_ALL. The main frame window usually has the IDR_MAINFRAME identifier. You might expect these identifiers to map directly to help context IDs. IDR_MAINFRAME, for example, would map to a help context ID of the same name. But what if a frame ID and a command ID had the same numeric value? Obviously, you need a way to prevent these overlaps. The application framework solves the overlap problem by defining a new set of help #define constants that are derived from program element IDs. These help constants are the sum of the element ID and a base value, as shown in the following table.

 

Program Element

Element ID Prefix

Help Context ID Prefix

Base (Hexadecimal)

Menu Item or toolbar button

ID_, IDM_

HID_, HIDM_

10000

Frame or dialog

IDR_, IDD_

HIDR_, HIDD

20000

Error message box

IDP_

HIDP_

30000

Non-client area

 

H…

40000

Control bar

IDW_

HIDW_

50000

Dispatch error messages

 -

 -

60000

 

Table 3.

 

HID_EDIT_CLEAR_ALL (0x1E121) corresponds to ID_EDIT_CLEAR_ALL (0xE121), and HIDR_MAINFRAME (0x20080) corresponds to IDR_MAINFRAME (0x80).

 

F1 Help

 

Two separate context-sensitive help access methods are built into an MFC application and are available if you have selected the AppWizard Context-Sensitive Help option. The first is standard F1 help. The user presses F1; the program makes its best guess about the help context and then calls WinHelp. In this mode, it is possible to determine the currently selected menu item or the currently selected window (frame, view, dialog, or message box).

 

Shift-F1 Help

 

The second context-sensitive help mode is more powerful than the F1 mode. With Shift-F1 help, the program can identify the following help contexts:

  • A menu item selected with the mouse cursor.

  • A toolbar button.

  • A frame window.

  • A view window.

  • A specific graphics element within a view window.

  • The status bar.

  • Various nonclient elements such as the system menu control.

 

Shift-F1 help doesn't work with modal dialogs or message boxes. The user activates Shift-F1 help by pressing Shift-F1 or by clicking the Context Help toolbar button, shown here.

 

Context Help button.

 

Figure 15: Context Help button.

 

 

In either case, the mouse cursor changes to: 

On the next mouse click, the help topic appears, with the position of the mouse cursor determining the context.

 

Message Box Help: The AfxMessageBox() Function

 

The global function AfxMessageBox() displays application framework error messages. This function is similar to the CWnd::MessageBox member function except that it has a help context ID as a parameter. The application framework maps this ID to a WinHelp context ID and then calls WinHelp when the user presses F1. If you can use the AfxMessageBox() help context parameter, be sure to use prompt IDs that begin with IDP_. In your RTF file, use help context IDs that begin with HIDP_. There are two versions of AfxMessageBox(). In the first version, the prompt string is specified by a character-array pointer parameter. In the second version, the prompt ID parameter specifies a string resource. If you use the second version, your executable program will be more efficient. Both AfxMessageBox() versions take a style parameter that makes the message box display an exclamation point, a question mark, or another graphics symbol.

 

Generic Help

 

When context-sensitive help is enabled, AppWizard assembles a series of default help topics that are associated with standard MFC library program elements. Following are some of the standard topics:

 

These topics are contained in the files AfxCore.rtf and AfxPrint.rtf, which are copied, along with the associated bitmap files, to the application's \hlp subdirectory. Your job is to customize the generic help files. AppWizard generates AfxPrint.rtf only if you specify the Printing And Print Preview option.

 

 

Continue on next module...part 3.

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. MSDN Library

  4. Windows data type.

  5. Win32 programming Tutorial.

  6. The best of C/C++, MFC, Windows and other related books.

  7. Unicode and Multibyte character set: Story and program examples.

 

 

 

 


 

| Tenouk C & C++ | MFC Home | Context-Sensitive Help 1 | Context-Sensitive Help 3 | Download | Site Index |