Programming for Context Help
Your first task in arranging for context Help is to get a Question button onto theOptions dialog box, because AppWizard already added one to the toolbar. Open the
Options dialog box by double-clicking it in the ResourceView and then choose View,
Properties. Click the Extended Styles tab and then make sure that the Context Help
check box is selected, as shown in Figure 11.5.
FIG. 11.5 Turn on the Question box on the Options dialog box of ShowString.
As mentioned earlier, two messages are relevant to context Help: WM_HELP when a
user clicks something while in What's This? mode, and WM_CONTEXTMENU when a user
right-clicks something. You need to arrange for your dialog box class, COptionsDialog,
to catch these messages. Because ClassWizard does not include them in the list of
messages it will catch, you will add entries outside the special ClassWizard comments.
The message map in OptionsDialog.h should look like this:
// Generated message map functions
//{{AFX_MSG(COptionsDialog)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
DECLARE_MESSAGE_MAP()
The message map in OptionsDialog.cpp should look like this:
BEGIN_MESSAGE_MAP(COptionsDialog, CDialog)
//{{AFX_MSG_MAP(COptionsDialog)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
ON_WM_HELPINFO()
ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
These macros arrange for WM_HELP to be caught by OnHelpInfo()and for
WM_CONTEXTMENU to be caught by OnContextMenu(). The next step is to write these
functions. They both need to use a table to connect resource IDs to Help topic IDs. To
create this table, add these lines at the be-ginning of OptionsDialog.cpp, after the
comment block that reads // COptionsDialog dialog:
static DWORD aHelpIDs[] =
{
IDC_OPTIONS_STRING, HIDD_OPTIONS_STRING,
IDC_OPTIONS_BLACK, HIDD_OPTIONS_BLACK,
IDC_OPTIONS_RED, HIDD_OPTIONS_RED,
IDC_OPTIONS_GREEN, HIDD_OPTIONS_GREEN,
IDC_OPTIONS_HORIZCENTER, HIDD_OPTIONS_HORIZCENTER,
IDC_OPTIONS_VERTCENTER, HIDD_OPTIONS_VERTCENTER,
IDOK, HIDD_OPTIONS_OK,
IDCANCEL, HIDD_OPTIONS_CANCEL,
0, 0
};
The Help system uses this array (you pass the address to the WinHelp() function) to
connect resource IDs and Help topic IDs. The compiler, however, has never heard of
HIDD_OPTIONS_STRING, so add these lines to OptionsDialog.h before the definition of
the COptionsDialog class:
#define HIDD_OPTIONS_STRING 2
#define HIDD_OPTIONS_BLACK 3
#define HIDD_OPTIONS_RED 4
#define HIDD_OPTIONS_GREEN 5
#define HIDD_OPTIONS_HORIZCENTER 6
#define HIDD_OPTIONS_VERTCENTER 7
#define HIDD_OPTIONS_OK 8
#define HIDD_OPTIONS_CANCEL 9
The numbers are chosen arbitrarily. Now, after the two functions are written, the
compiler will be happy because all these constants are defined. The Help system,
however, does not know what's going on because these topics aren't in the Help mapping
file yet. Therefore, add these lines to ShowStringX.hm:
HIDD_OPTIONS_STRING 0x02
HIDD_OPTIONS_BLACK 0x03
HIDD_OPTIONS_RED 0x04
HIDD_OPTIONS_GREEN 0x05
HIDD_OPTIONS_HORIZCENTER 0x06
HIDD_OPTIONS_VERTCENTER 0x07
HIDD_OPTIONS_OK 0x08
HIDD_OPTIONS_CANCEL 0x09
Be sure to use the same numbers as in the #define statements in OptionsDialog.h. The
stage is set; all that remains is to add the code for the functions at the end of
OptionsDialog.cpp. Here's what OnHelpInfo() looks like:
BOOL COptionsDialog::OnHelpInfo(HELPINFO *lpHelpInfo)
{
if (lpHelpInfo->iContextType == HELPINFO_WINDOW)
// must be for a control
{
// have to call SDK WinHelp not CWinApp::WinHelp
// because CWinApp::WinHelp does not take a
// handle as a parameter.
::WinHelp((HWND)lpHelpInfo->hItemHandle,
AfxGetApp()->m_pszHelpFilePath,
HELP_WM_HELP, (DWORD)aHelpIDs);
}
return TRUE;
}
This function calls the SDK WinHelp() function and passes the handle to the control,
the path to the Help file, the command HELP_WM_HELP to request a context-sensitive
pop-up Help topic, and the table of resource IDs and Help topic IDs built earlier. There is
no other work for your function to do after kicking WinHelp() into action.
TIP: If you've never seen the :: scope resolution operator used without a
classname before it, it means "call the function that isn't in any class," and
in Windows programming, that generally means the SDK function.
NOTE: The third parameter of this call to WinHelp() directs the Help
system to put up a certain style of Help window. HELP_WM_HELP gives you
a pop-up menu, as does HELP_WM_CONTEXTMENU. HELP_CONTEXT
produces an ordinary Help window, which can be resized and moved, and
enables Help navigation. HELP_FINDER opens the Help Topics dialog box.
HELP_CONTENTS and HELP_INDEX are obsolete and should be replaced
with HELP_FINDER if you maintain code that uses them.
OnContextMenu() is even simpler. Add this code at the end of OptionsDialog.cpp:
void COptionsDialog::OnContextMenu(CWnd *pWnd, CPoint /*point*/)
{
::WinHelp((HWND)*pWnd, AfxGetApp()->m_pszHelpFilePath,
HELP_CONTEXTMENU, (DWORD)aHelpIDs);
}
This function does not need to check that the right-click is on a control as
OnHelpInfo() did, so it just calls the SDK WinHelp(). WinHelp() takes care of displaying
the shortcut menu with only a What's This item and then displays Help when that item is
chosen.
To check your typing, build the project by choosing Build, Build and then compile the
Help file by giving focus to ShowString.hpj and choosing Build, Compile. (You can also
right-click ShowString.hpj in the FileView of the Project Workspace window and choose
Compile from the shortcut menu.) There is not much point in testing it, though; the
AppWizard stuff is sure to work, and without Help content connected to those topics,
none of the code you just added can succeed in displaying content.
No comments:
Post a Comment