How To Add Toolbars and Tooltips to ActiveX Controls

Article translations Article translations
Article ID: 194294 - View products that this article applies to.
This article was previously published under Q194294
Expand all | Collapse all

SUMMARY

An ActiveX control can have a toolbar (a CToolBar class) as its child window. This article shows a way to create such a toolbar and also how to implement tooltips for buttons on the toolbar window.

MORE INFORMATION

Visual C++ provides two methods to create a toolbar. The article desribes how to create a toolbar resource using the Resource Editor. If you already have a bitmap resource, please refer to the online documentation "Converting Bitmaps to Toolbars" for converting your bitmap resource to a toolbar resource.

Steps are shown below:

  1. Use the MFC ActiveX Control Wizard to generate an MFC ActiveX control.
  2. Create a Toolbar resource in the control's project.
  3. Add a tooltip string resource for each button in the toolbar. These tooltip string resources will be loaded in the TTN_NEEDTEXT notification code handler.
  4. Add a WH_GETMESSAGE hook callback function to the ActiveX control- derived class. The hook procedure is in charge of calling the application's PreTranslateMessage(), and this results in the call to FilterToolTipMessage(), which activates tooltips. A hook procedure is needed because the ActiveX control is just like an inproc server[ASCII 151]no message pump is found:
          HHOOK hHook = NULL;
    
          // Hook procedure for WH_GETMESSAGE hook type.
          LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM
             lParam)
          {
            // Switch the module state for the correct handle to be used.
            AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
    
            // If this is a keystrokes message, translate it in controls'
            // PreTranslateMessage().
            LPMSG lpMsg = (LPMSG) lParam;
    
            if( (nCode >= 0) &&
              PM_REMOVE == wParam &&
              AfxGetApp()->PreTranslateMessage(lpMsg))
            {
               lpMsg->message = WM_NULL;
               lpMsg->lParam = 0L;
               lpMsg->wParam = 0;
            }
    
    
           // Passes the hook information to the next hook procedure in
           // the current hook chain.
           return ::CallNextHookEx(hHook, nCode, wParam, lParam);
          }
    					
  5. Create the toolbar window (a CToolBar class), which is a child window of the ActiveX control. This is done in response to WM_CREATE message. In addition, WM_CREATE message handler is also a good place to install the WH_GETMESSAGE hook procedure.
          int CCToolBarCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
          {
             if (COleControl::OnCreate(lpCreateStruct) == -1)
                return -1;
    
             // Create a CToolBar window which is a child of ActiveX control.
             if (!m_ToolBar.Create(this,
                   WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS) ||
                  !m_ToolBar.LoadToolBar(IDR_TOOLBAR))
                {
                   TRACE0("Failed to create toolbar\n");
                   return -1;      // fail to create
                }
    
             // Toolbar has to have TBSTYLE_TOOLTIPS style. Otherwise,
             // notification handler for TTN_NEXTTEXT won't be called.
             m_ToolBar.ModifyStyle (0, TBSTYLE_TOOLTIPS);
    
             // Move the toolbar so it is VISIBLE on the screen.
             CRect rc;
             GetClientRect(&rc);
             rc.bottom = rc.top + 34;
             m_ToolBar.MoveWindow(&rc);
    
             // Because ActiveX control is an inproc server, it does not have a
             // message pump. So, messages to child windows created by the
             // ActiveX control are not going to be received by the control.
             // Thus, we set up a message hook to call PreTranslateMessage().
             // This results in the call to FilterToolTipMessage(), which
             // activates tooltips.
             hHook = ::SetWindowsHookEx(
                WH_GETMESSAGE,
                GetMessageProc,
                AfxGetInstanceHandle(),
                GetCurrentThreadId());
             ASSERT (hHook);
    
             return 0;
          }
    					
  6. Uninstall the message hook function in response to WM_DESTROY message:
          void CCToolBarCtrl::OnDestroy()
          {
             // Remove the message hook function.
             VERIFY (::UnhookWindowsHookEx (hHook));
    
             COleControl::OnDestroy();
          }
    					
  7. Add a TTN_NEEDTEXTW (for Unicode notification code) or TTN_NEEDTEXTA (for ANSI notification code) notification handler to the ActiveX control-derived class. Load the tooltip string to be displayed in this notification code handler:
          BEGIN_MESSAGE_MAP(CCToolBarCtrl, COleControl)
             //{{AFX_MSG_MAP(CCToolBarCtrl)
             ON_WM_CREATE()
             ON_COMMAND(ID_BUTTON1, OnButton1) // first button on toolbar
             ON_COMMAND(ID_BUTTON2, OnButton2) // second button on toolbar
             ON_COMMAND(ID_BUTTON3, OnButton3) // third button on toolbar
             ON_WM_DESTROY()
             //}}AFX_MSG_MAP
             ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
    
             // ANSI notification code (for Windows 95)
             ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
    
             // Unicode notification code (for NT)
             ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
          END_MESSAGE_MAP()
    
          // Notification handler for tooltips - determine which tooltip
          // string resource to be displayed.
          BOOL CCToolBarCtrl::OnToolTipNotify(
             UINT id, NMHDR * pNMHDR, LRESULT * pResult)
          {
             TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*) pNMHDR;
             TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*) pNMHDR;
    
             int strid = 0;
             switch (pNMHDR->idFrom)
             {
             case ID_BUTTON1:
                strid = IDS_BUTTON1;
                break;
    
             case ID_BUTTON2:
                strid = IDS_BUTTON2;
                break;
    
             case ID_BUTTON3:
                strid = IDS_BUTTON3;
                break;
             }
    
      if (strid)
           {
              *pResult = 0;
      
              CString str;
              str.LoadString(strid);
      
              #define _countof(array) (sizeof(array)/sizeof(array[0]))
      
              #ifndef _UNICODE
              if (pNMHDR->code == TTN_NEEDTEXTA)
              lstrcpyn(pTTTA->szText, str, _countof(pTTTA->szText));
              else
              _mbstowcsz(pTTTW->szText, str, _countof(pTTTW->szText));
              #else
              if (pNMHDR->code == TTN_NEEDTEXTA)
              _wcstombsz(pTTTA->szText, str, _countof(pTTTA->szText));
              else
              lstrcpyn(pTTTW->szText, str, _countof(pTTTW->szText));
              #endif
      
               return TRUE;
            }
    
             return FALSE;
          }
     
    					
(c) Microsoft Corporation 1998, All Rights Reserved. Contributions by Yeong- Kah Tam, Microsoft Corporation.

Properties

Article ID: 194294 - Last Review: November 21, 2006 - Revision: 2.2
APPLIES TO
  • Microsoft Foundation Class Library 4.2, when used with:
    • Microsoft Visual C++ 4.0 Standard Edition
    • Microsoft Visual C++ 4.1 Subscription
    • Microsoft Visual C++ 4.2 Enterprise Edition
    • Microsoft Visual C++ 4.2 Professional Edition
    • Microsoft Visual C++ 5.0 Enterprise Edition
    • Microsoft Visual C++ 5.0 Professional Edition
Keywords: 
kbhowto kbmfcctrlbar kbtoolbar KB194294
Retired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com