Introduction
I am implementing context-sensitive Help in my MFC app, and, as always with Windows programming, it isn't quite as simple as we'd like it to be. I found that to get the behavior I wanted, I had to tweak the message handling in the dialogs and Property Sheets a little. The result was that I created 2 base classes for all my dialogs and Property Sheets. These are CHelpDlg
and CHelpPrSheet
. You should be able to use these as is in your apps as well.
Features
- Provides general Help for the dialog when F1 is pressed.
- Provides context Help for the control with focus when Shift + F1 is pressed. (An alternative is to show the floating pointer when Shift + F1 is pressed. See code for how to do this.)
- Provides context-sensitive Help for controls in your dialog.
- (Dialog only) Provides general Help for the dialog if you include a button with ID =
IDHELP
.
Requirements
When creating your Visual Studio project, make sure you check Context-sensitive Help in the AppWizard. I'm assuming you are somewhat familiar with the support that MFC provides for context-sensitive Help. If not, read TN028 on MSDN.
Dialog Boxes
- Build your dialog box using the resource editor as you normally would.
- If you want context-sensitive Help, make sure you check the Context Help check box in the More Styles tab of the resource editor.
- For any controls that you want context-sensitive Help, make sure you check the Help ID check box in the General tab of the resource editor.
- If you want a Help button in your dialog, put one there with the ID =
IDHELP
.
- Use Class Wizard and derive from
CDialog
.
- Edit the .h and .cpp files and make
CHelpDlg
the base class instead of CDialog
. Note: you must replace all refs to CDialog
with CHelpDlg
.
Property Sheets
- Build your Property Pages as you normally would.
- If you want context-sensitive Help, make sure you check the Context Help check box in the More Styles tab of the resource editor.
- For any controls that you want context-sensitive Help, make sure you check the Help ID check box in the General tab of the resource editor.
- Use Class Wizard and derive from
CPropertyPage
as you normally would.
- Use Class Wizard and create a new class derived from
CPropertySheet
.
- Edit the .h and .cpp files and make
CHelpPrSheet
the base class instead of CPropertySheet
. Note you must replace all refs to CPropertySheet
with CHelpPrSheet
.
Implementation Notes
There are 2 main tricks employed here. First, is handling the WM_HELPINFO
message. The default handler that MFC supplies doesn't do the right thing for context Help. Here is what the handler looks like:
BOOL CHelpDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
if(pHelpInfo->iContextType == HELPINFO_WINDOW) {
AfxGetApp()->WinHelp(pHelpInfo->dwContextId, HELP_CONTEXTPOPUP);
}
return(TRUE);
}
The other trick is figuring out what you want to do with F1 and Shift + F1. My solution is to trap a magical mystical undocumented MFC msg 0x4d and handle it in PreTranslateMessage
as shown below:
BOOL CHelpDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == 0x4d)
{
if (GetKeyState(VK_SHIFT) > = 0)
{
OnCommandHelp(0, 0);
return(TRUE);
}
#ifdef FLOATING_ARROW
else
{
SendMessage(WM_SYSCOMMAND, SC_CONTEXTHELP);
return(TRUE);
}
#endif
}
return CDialog::PreTranslateMessage(pMsg);
}