DOCUMENT:Q194294 17-JUL-2001 [visualc] TITLE :HOWTO: Add Toolbars and Tooltips to ActiveX Controls PRODUCT :Microsoft C Compiler PROD/VER:winnt:4.0,4.1,4.2,5.0 OPER/SYS: KEYWORDS:kbole kbActiveX kbMFC kbToolbar kbVC kbocx kbGrpDSMFCATL kbMFCCtrlBar ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - The Microsoft Foundation Classes (MFC), used with: - Microsoft Visual C++, 32-bit Editions, versions 4.0, 4.1 - Microsoft Visual C++, 32-bit Enterprise Edition, version 4.2 - Microsoft Visual C++, 32-bit Professional Edition, version 4.2 - Microsoft Visual C++, 32-bit Enterprise Edition, version 5.0 - Microsoft Visual C++, 32-bit Professional Edition, version 5.0 ------------------------------------------------------------------------------- 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. (c) Microsoft Corporation 1998, All Rights Reserved. Contributions by Yeong-Kah Tam, Microsoft Corporation Additional query words: ocx ====================================================================== Keywords : kbole kbActiveX kbMFC kbToolbar kbVC kbocx kbGrpDSMFCATL kbMFCCtrlBar Technology : kbAudDeveloper kbMFC Version : winnt:4.0,4.1,4.2,5.0 Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.