The TippyDialogMaster Application

There are probably many ways to create a class of dialog that accommodates ToolTips for its controls. I elected to derive a CTippyDialog class from CDialog to serve as a basis for future modal dialogs. (Since my method involves using variables in the main application object derived from CWinApp, it's not appropriate in situations where more than one dialog could appear on the screen at one time. This limitation basically means you can't use this method for modeless dialogs.) The new class overrides OnInitDialog and PostNcDestroy, plus it has a new data member called m_tip and a member function named EnumChildProc whose purpose will be apparent in a moment.


   class CTippyDialog : public CDialog
   {public:
       CTippyDialog(UINT id, CWnd* parent = NULL);
 
       CToolTipCtrl    m_tip;
 
       //{{AFX_VIRTUAL(CTippyDialog)
       virtual BOOL OnInitDialog();
       virtual void PostNcDestroy();
       //}}AFX_VIRTUAL
 
       static BOOL CALLBACK 
              EnumChildProc(HWND hwnd, LPARAM lParam);
   };
       The tool tips for a dialog's controls belong to the m_tip control in CTippyDialog. For the control to work, you need to do several things that aren't immediately obvious. You must modify the application's message loop to route mouse messages to the ToolTip control—that's how the control knows when and where to display a tip balloon. You must connect the control to the visible controls in the dialog by sending it TTM_ADDTOOL messages. You must also add string resources to the project so the ToolTip control knows which text to display in the balloons.
       I made the message-loop modification by adding m_dialog and m_tip variables to the main application class. m_dialog points to the one-and-only modal dialog that's currently being displayed, or else it's NULL. m_tip points to the m_tip member of that dialog. Then I overrode the ProcessMessageFilter member of the main application class to call CToolTipCtrl::RelayEvent at the appropriate time:

   BOOL CTippyDlgMasterApp::ProcessMessageFilter
          (int code, LPMSG lpMsg)
     {
   if (m_dialog && m_tip
       && (lpMsg->hwnd == m_dialog->m_hWnd
       || ::IsChild(m_dialog->m_hWnd, lpMsg->hwnd)))
         
       m_tip->RelayEvent(lpMsg);
     
   return CWinApp::ProcessMessageFilter(code, lpMsg);
   }
       Figure A shows the important member functions of CTippyDialog. In summary, the override for OnInitDialog sets the m_dialog and m_tip variables in the application object. It then enumerates all of the controls in the dialog in order to call CToolTipCtrl::Create to create ToolTips for each of them.
       I've only shown the bare basics here. The complete source code for the TippyDialog wizard is available from the link at the top of this article.