Implementing Context-sensitive Help in MFC Apps






3.83/5 (6 votes)
Nov 23, 1999
2 min read

125793

2705
Implementing context-sensitive Help in MFC apps.
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 ofCDialog
. Note: you must replace all refs toCDialog
withCHelpDlg
.
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 ofCPropertySheet
. Note you must replace all refs toCPropertySheet
withCHelpPrSheet
.
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) { // TODO: Add your message handler code here and/or call default 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) { // TODO: Add your specialized code here and/or call the base class // Magical mystical MFC F1 Help msg! if(pMsg->message == 0x4d) { if (GetKeyState(VK_SHIFT) > = 0) { // Shift key not down // Supply general dialog level help OnCommandHelp(0, 0); return(TRUE); // Eat it } #ifdef FLOATING_ARROW else { // Use this if you want Shift+F1 // to create the floating arrow instead SendMessage(WM_SYSCOMMAND, SC_CONTEXTHELP); return(TRUE); } #endif // FLOATING_ARROW } return CDialog::PreTranslateMessage(pMsg); }