You create a sample MFC feature pack based SDI/MDI application with context sensitive help support. However, the context sensitive help may not work with submenu items. This blog attempts to get this working.

 

clip_image001[4]

Figure 1: Context sensitive help for submenu item “View | Application Look | Office XP”

 

By default, when you create a sample MFC feature pack SDI/MDI application, the framework creates all the help files (.htm, .hhk, .hhp) with correct mapping for the top level menu items, including “ File | New”, “View | Status Bar”, etc. However, we don’t see any of these files created for submenu items. Now, since the files were not created for the submenu items, the help APIs could not find them and hence context sensitive help do not work and we may get unexpected results. If you manually create the help files (.htm) with correct mappings (.hhp) this will work.

 

Here are the steps to get this working:

Step 1: Create an .htm file associated with the submenu item in the directory “\hlp” where other .htm files are located.

Step 2: Name the file in format h[submenu item ID].htm . For example, hid_view_applook_off_xp.htm. Here ID_VIEW_APPLOOK_OFF_XP is the submenu item ID which we can get from Properties.

Step 3: Edit the file with the required help content. You can also copy the contents from existing .htm file for reference.

Step 4: Add this newly created .htm file in the project under “HTML Help Files” section.

Step 5: Edit the application .hhp file and add the file and mappings for the .htm file under “[FILES]” section and “[ALIAS]” section

Step 6: Rebuild the project

Step 7: Start the application and float over the mouse on the submenu item and hit “F1”. You will see the help file!

 

Unfortunately for an MDI application, you have to additionally tweak the code to handle the OnHelpInfo() due to a known issue in MFC Library. The reason for the MDI application to fail is related to the fact that CMDIChildWnd derives from CFrameWnd, so it has an m_nIDTracking and implements IsTracking(). When the OnCommandHelp() method is called on the CMDIChildWnd, the implementation in the CFrameWnd class is called, but the CMDIChildWnd does not have the tracking ID set. Due to this AFX_IDS_IDLEMESSAGE incorrectly gets assigned to CFrameWnd::m_nIDTracking instead of the submenu item ID. If you wish to know how the tracking is done, have a look at below code snippet, part of “C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\winfrm.cpp” @ 272. The commented line number 6 shows the expected path of execution for an SDI application. Because the tracking is incorrect, the code path in line number 9 executes and hence the problem with MDI.

 

  1. LRESULT CFrameWnd::OnCommandHelp(WPARAM, LPARAM lParam)
  2. {
  3.     if (lParam == 0)
  4.     {
  5.         if (IsTracking())
  6.             // Expected line of code in working scenario   
  7.             lParam = HID_BASE_COMMAND+m_nIDTracking;
  8.         else
  9.             lParam = HID_BASE_RESOURCE+m_nIDHelp;
  10.     }
  11.     if (lParam != 0)
  12.     {
  13.         CWinApp* pApp = AfxGetApp();
  14.         if (pApp != NULL)
  15.             pApp->WinHelpInternal(lParam);
  16.         return TRUE;
  17.     }
  18.     return FALSE;
  19. }

 

One of the way to work-around this behavior is to override the OnHelpInfo() function in the main frame class as below. The fix is to defer to the parent frame, to get the tracking ID, if the CFrameWnd is really a CMDIChildWnd. This could be achieved using below code snippet.

 

  1. BOOL CMainFrame::OnHelpInfo(HELPINFO* pHelpInfo)
  2. {    
  3.     if( GetKeyState(VK_SHIFT) >= 0
  4.     &&  GetKeyState(VK_CONTROL) >= 0
  5.     &&  GetKeyState(VK_MENU) >= 0 )
  6.     {
  7.         SendMessage(WM_COMMANDHELP);
  8.         return TRUE;
  9.     }
  10.     return CMDIFrameWndEx::OnHelpInfo(pHelpInfo);
  11. }

 

Now your MDI application will fully support context sensitive help for submenu items as well. To know more information on Context-Sensitive Help for your programs, see http://msdn.microsoft.com/en-us/library/dyd1yfww(VS.80).aspx

 

- Gaurav Patole

Technical Lead, Developer Support – Languages Team.