HOWTO: Add Toolbars and Tooltips to ActiveX Controls
ID: Q194294
|
The information in this article applies to:
-
The Microsoft Foundation Classes (MFC), included with:
-
Microsoft Visual C++, 32-bit Editions, versions 4.0, 4.1, 4.2, 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:
- Use the MFC ActiveX Control Wizard to generate an MFC ActiveX control.
- Create a Toolbar resource in the control's project.
- 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.
- 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);
}
- 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;
}
- Uninstall the message hook function in response to WM_DESTROY message:
void CCToolBarCtrl::OnDestroy()
{
// Remove the message hook function.
VERIFY (::UnhookWindowsHookEx (hHook));
COleControl::OnDestroy();
}
- 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.
© Microsoft Corporation 1998, All Rights Reserved. Contributions by Yeong-Kah Tam, Microsoft Corporation
Additional query words:
ocx
Keywords : kbole kbActiveX kbMFC kbVC kbocx
Version : winnt:4.0,4.1,4.2,5.0
Platform : winnt
Issue type : kbhowto
|