| Tenouk C & C++ | MFC Home | Context-Sensitive Help 2 | C++, MFC & DLL 1 | Download | Site Index |


 

 

 

 

 

Module 15b:

Context-Sensitive Help 3

 

 

 

 

 

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. A Help Example: No Programming Required

  2. The MAKEHELP Process

  3. Help Command Processing

  4. F1 Processing

  5. Shift-F1 Processing

  6. A Help Command Processing Example: MYMFC22B

  7. Header Requirements

  8. CStringView Class

  9. CHexView Class

  10. Resource Requirements

  11. Help File Requirements

  12. Testing the MYMFC22B Application

 

 

 

A Help Example: No Programming Required

 

If you followed the instructions for MYMFC21D in Module 20, you already selected the AppWizard Context-Sensitive Help option. We'll now return to that example and explore the application framework's built-in help capability. You'll see how easy it is to link help topics to menu command IDs and frame window resource IDs. You edit RTF files, not CPP files. Here are the steps for customizing the help for MYMFC21D:

 

Verify that the help file was built correctly. If you have built the MYMFC21D project already, chances are that the help file was created correctly as part of the build process. Check this by running the application and then pressing the F1 key. You should see the generic Application Help screen with the title "Modifying the Document", something like as shown below.

 

Verifying that the help file was built correctly in MYMFC21D.

 

Figure 16: Verifying that the help file was built correctly in MYMFC21D.

If you do not see this screen, the MAKEHELP batch file did not run correctly. First check the last two lines of the mymfc21D.hpj file in the \hlp subdirectory. Are the paths correct for your Visual C++ installation? Next choose Options from the Tools menu, and click on the Directories tab. Make sure that the \VC98\bin subdirectory of your Visual C++ directory is one of the search directories for Executable Files.

 

Verifying the executable path for visual C++ 6.0.

 

Figure 17: Verifying the executable path for visual C++ 6.0.

 

To generate the help file, highlight the mymfc21D.hpj file in the Workspace FileView window, and then choose Compile Mymfc21D.hpj from the Build menu or select the Compile Mymfc21D.hpj menu from the mouse right click action.

 

Compiling the mymfc21D.hpj file to generate WinHelp through Build menu.

 

Figure 18: Compiling the mymfc21D.hpj file to generate WinHelp through Build menu.

 

Compiling the mymfc21D.hpj file to generate WinHelp through FileView.

 

Figure 19: Compiling the mymfc21D.hpj file to generate WinHelp through FileView.

 

This runs the MAKEHELP batch file that is in your project directory. You can also run it directly from an MS-DOS prompt. You should observe some "file(s) copied" messages but no error messages. Rerun the MYMFC21D program, and press F1 again.

The Visual C++ make processor doesn't always detect all the dependencies in your help system. Sometimes you must run the MAKEHELP batch file yourself to rebuild the HLP file after making changes.

 

Test the generic help file. Try the following experiments:

 

The WinHelp when F1 or Alt-F key is pressed.

 

Figure 20: The WinHelp when F1 or Alt-F key is pressed.

Using Context help button to invoke the WinHelp.

 

Figure 21: Using Context help button to invoke the WinHelp.

Using Context help to invoke the Title bar help.

 

Figure 22: Using Context help to invoke the Title bar help.

Pressing F1, invoking the help main index page.

 

Figure 23: Pressing F1, invoking the help main index page.

 

Change the application title. The file AfxCore.rtf, in the \mfcproject\mymfc21D\hlp directory, contains the string <<YourApp>> throughout. Open the AfxCore.rtf and replace it globally with MYMFC21D.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Modifying the AfxCore.rtf to reflect our real WinHelp content.

 

Figure 24: Modifying the AfxCore.rtf to reflect our real WinHelp content.

 

Change the Modifying The Document Help screen. The file AfxCore.rtf in the \mfcproject\mymfc21D\hlp directory contains text for the generic Application Help screen. Search for Modifying the Document, and then change the text to something appropriate for the application. This topic has the help context ID HIDR_DOC1TYPE. The generated mymfc21D.hpj file provides the alias HIDR_MYMFC21DTYPE.

 

Add a topic for the Window New String Window menu item. The New String Window menu item was added to MYMFC21D and thus didn't have associated help text. Add a topic to AfxCore.rtf, as shown here.

 

Modifying the AfxCore.rtf to reflect our real WinHelp content.

 

Figure 25: Modifying the AfxCore.rtf to reflect our real WinHelp content.

 

Notice the # footnote that links the topic to the context ID HID_WINDOW_NEW_STRING as defined in hlp\mymfc21D.hm. The program's command ID for the New String Window menu item is, of course, ID_WINDOW_NEW_STRING.

 

Rebuild the help file and test the application. Run the MAKEHELP batch file again, from the FileView or Build menu, and then rerun the MYMFC21D program. Try the two new help links.

 

Our rebuilt WinHelp.

 

Figure 26: Our rebuilt WinHelp.

 

The MAKEHELP Process

 

The process of building the application's HLP file is complex. Part of the complexity results from the Help Compiler's non-acceptance of statements such as:

 

HID_MAINFRAME = ID_MAINFRAME + 0x20000

 

Because of the Help Compiler's non-acceptance, a special preprocessing program named makehm.exe must read the resource.h file to produce a help map file that defines the help context ID values. Below is a diagram of the entire MAKEHELP process.

 

The MAKEHELP process.

 

Figure 27: The MAKEHELP process.

 

AppWizard generates the application's help project file (HPJ) and the help contents file (CNT). In the project file, the [FILES] section brings in RTF files and the [MAP] section contains #include statements for the generic and the application-specific help map (HM) files. The Help Workshop (HCRTF.EXE) processes the project file to produce the help file that WinHelp reads.

 

Help Command Processing

 

You've seen the components of a help file, and you've seen the effects of F1 and Shift-F1. You know how the application element IDs are linked to help context IDs. What you haven't seen is the application framework's internal processing of the help requests. Why should you be concerned? Suppose you want to provide help on a specific view window instead of a frame window. What if you need help topics linked to specific graphics items in a view window? These and other needs can be met by mapping the appropriate help messages in the view class. Help command processing depends on whether the help request was an F1 request or a Shift-F1 request. The processing of each help request will be described separately.

 

F1 Processing

 

The F1 key is normally handled by a keyboard accelerator entry that AppWizard inserts in the RC file. The accelerator associates the F1 key with an ID_HELP command that is sent to the OnHelp() member function in the CFrameWnd class.

 

In an active modal dialog or a menu selection in progress, the F1 key is processed by a Windows hook that causes the same OnHelp() function to be called. The F1 accelerator key would otherwise be disabled.

 

The CFrameWnd::OnHelp function sends an MFC-defined WM_COMMANDHELP message to the innermost window, which is usually the view. If your view class does not map this message or if the handler returns FALSE, the framework routes the message to the next outer window, which is either the MDI child frame or the main frame. If you have not mapped WM_COMMANDHELP in your derived frame window classes, the message is processed in the MFC CFrameWnd class, which displays help for the symbol that AppWizard generates for your application or document type. If you map the WM_COMMANDHELP message in a derived class, your handler must call CWinApp::WinHelp with the proper context ID as a parameter. For any application, AppWizard adds the symbol IDR_MAINFRAME to your project and the HM file defines the help context ID HIDR_MAINFRAME, which is aliased to main_index in the HPJ file. The standard AfxCore.rtf file associates the main index with this context ID. For an MDI application named SAMPLE, for example, AppWizard also adds the symbol IDR_SAMPLETYPE to your project and the HM file defines the help context ID HIDR_SAMPLETYPE, which is aliased to HIDR_DOC1TYPE in the HPJ file. The standard AfxCore.rtf file associates the topic "Modifying the Document" with this context ID.

 

Shift-F1 Processing

 

When the user presses Shift-F1 or clicks the Context Help toolbar button, a command message is sent to the CFrameWnd function OnContextHelp(). When the user presses the mouse button again after positioning the mouse cursor, an MFC-defined WM_HELPHITTEST message is sent to the innermost window where the mouse click is detected. From that point on, the routing of this message is identical to that for the WM_COMMANDHELP message, described previously in "F1 Processing". The lParam parameter of OnHelpHitTest() contains the mouse coordinates in device units, relative to the upper-left corner of the window's client area. The y value is in the high-order half; the x value is in the low-order half. You can use these coordinates to set the help context ID specifically for an item in the view. Your OnHelpHitTest() handler should return the correct context ID; the framework will call WinHelp.

 

A Help Command Processing Example: MYMFC22B

 

MYMFC22B is based on example MYMFC21D from Module 21. It's a two-view MDI application with view-specific help added. Each of the two view classes has an OnCommandHelp() message handler to process F1 help requests and an OnHelpHitTest() message handler to process Shift-F1 help requests. Make a copy of the MYMFC21D project folder as a backup. Use the original for this exercise. All the following codes copied into those relevant files manually.

 

Header Requirements

 

The compiler recognizes help-specific identifiers only if the following #include statement is present:

 

#include <afxpriv.h>

 

MFC Visual C++ code segment

 

Listing 1.

 

In MYMFC22B, the statement is in the StdAfx.h file.

 

CStringView Class

 

The modified string view in StringView.h needs message map function prototypes for both F1 help and Shift-F1 help, as shown here:

 

afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam);

afx_msg LRESULT OnHelpHitTest(WPARAM wParam, LPARAM lParam);

 

MFC Visual C++ code segment

 

Listing 2.

 

Here are the message map entries in StringView.cpp:

 

ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)

ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)

 

MFC Visual C++ code segment

 

Listing 3.

 

 

The OnCommandHelp() message handler member function in StringView.cpp processes F1 help requests. It responds to the message sent from the MDI main frame and displays the help topic for the string view window, as shown here:

 

LRESULT CStringView::OnCommandHelp(WPARAM wParam, LPARAM lParam)

{

    if (lParam == 0) { // context not already determined

        lParam = HID_BASE_RESOURCE + IDR_STRINGVIEW;

    }

    AfxGetApp()->WinHelp(lParam);

    return TRUE;

}

 

MFC Visual C++ code segment

 

Listing 4.

 

Finally the OnHelpHitTest() member function handles Shift-F1 help, as shown here:

 

LRESULT CStringView::OnHelpHitTest(WPARAM wParam, LPARAM lParam)

{

    return HID_BASE_RESOURCE + IDR_STRINGVIEW;

}

 

MFC Visual C++ code segment

 

Listing 5.

 

In a more complex application, you might want OnHelpHitTest() to set the help context ID based on the mouse cursor position.

 

CHexView Class

 

The CHexView class processes help requests the same way as the CStringView class does. Following is the necessary header code in HexView.h:

 

afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam);

afx_msg LRESULT OnHelpHitTest(WPARAM wParam, LPARAM lParam);

 

MFC Visual C++ code segment

 

Listing 6.

 

Here are the message map entries in HexView.cpp:

 

ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)

ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)

 

MFC Visual C++ code segment

 

Listing 7.

 

And here is the implementation code in HexView.cpp:

 

LRESULT CHexView::OnCommandHelp(WPARAM wParam, LPARAM lParam)

{

    if (lParam == 0) { // context not already determined

        lParam = HID_BASE_RESOURCE + IDR_HEXVIEW;

    }

    AfxGetApp()->WinHelp(lParam);

    return TRUE;

}

 

LRESULT CHexView::OnHelpHitTest(WPARAM wParam, LPARAM lParam)

{

    return HID_BASE_RESOURCE + IDR_HEXVIEW;

}

 

MFC Visual C++ code segment

 

Listing 8.

 

Resource Requirements

 

Two new symbols were added to the project's Resource.h file. Their values and corresponding help context IDs are shown here.

 

Symbol

Value

Help Context ID

Value

IDR_STRINGVIEW

101

HIDR_STRINGVIEW

0x20065

IDR_HEXVIEW

102

HIDR_HEXVIEW

0x20066

 

Table 4

 

Invoking the resource symbol dialog.

 

Figure 28: Invoking the resource symbol dialog.

 

Adding new resource symbols.

 

Figure 29: Adding new resource symbols.

 

Help File Requirements

 

Two topics were added to the AfxCore.rtf file with the help context IDs HIDR_STRINGVIEW and HIDR_HEXVIEW, as shown here.

 

Adding two new help topics to the AfxCore.rtf file.

 

Figure 30: Adding two new help topics to the AfxCore.rtf file.

 

The generated mymfc22B.hm file, in the project's \hlp subdirectory, should look something like this:

 

// MAKEHELP.BAT generated Help Map file.  Used by MYMFC22B.HPJ.

 

// Commands (ID_* and IDM_*)

HID_WINDOW_NEW_STRING                   0x18003

HID_WINDOW_NEW_HEX                      0x18005

 

// Prompts (IDP_*)

 

// Resources (IDR_*)

HIDR_STRINGVIEW                         0x20065

HIDR_HEXVIEW                            0x20066

HIDR_MAINFRAME                          0x20080

HIDR_MYMFC22BTYPE                       0x20081

 

// Dialogs (IDD_*)

HIDD_ABOUTBOX                           0x20064

 

// Frame Controls (IDW_*)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

mymfc21D.hm file content.

 

Figure 31: mymfc21D.hm file content.

 

Testing the MYMFC22B Application

 

Open a string child window and a hexadecimal child window. Test the action of F1 help and Shift-F1 help within those windows. If the help file didn't compile correctly, follow the instructions in the previous step of the help example in "A Help Example: No Programming Required".

 

The MYMFC22B (MYMFC21D) output used to test the F1 and Shift-F1 help functionalities.

 

Figure 32: The MYMFC22B (MYMFC21D) output used to test the F1 and Shift-F1 help functionalities.

 

When the F1 is hit the following help windows launched.

 

WinHelp when F1 key is pressed for string window.

 

Figure 33: WinHelp when F1 key is pressed for string window.

 

And another one for the Hex view.

 

Invoking the Hex window.

 

Figure 34: Invoking the Hex window.

 

WinHelp when Shift-F1 key is pressed for Hex window.

 

Figure 35: WinHelp when Shift-F1 key is pressed for Hex window.

 

 

 

 

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 2 | C++, MFC & DLL 1 | Download | Site Index |