I have always been perplexed by the question "which's the tool-tip associated with ComboBox?". On the internet, I searched a lot for samples about this, but the samples looked so complex, and some of the samples wrapped the ComboBox using separate controls
CButton, requiring to generate many extra classes for the ComboBox, resulting in lots of work to maintain the ComboBox. A couple of samples used hooks for window subclassing so that all the messages go to a new
WindowProc (window procedure) before going to the ComboBox, ummm..., that's very useful. But that is still not enough. Thus, based on these samples, I wrapped an enhanced class
CTTCombobox. According to the expectation, they use the new
WindowProc to hold the ListBox's messages and to do the tool-tip things. By the way, for the enhanced class
CTTCombobox, the source files contain only TTCombobox.h and TTCombobox.cpp, which is very easy to embed into your VC++ project.
CTTComboBox isn't wrapped using separate controls
- The class
CTTComboBox is derived from an MFC class
CCombobox. You can immediately use the class
CTTComboBox as well as derive new classes from it.
- By default, tool-tip is allowed for the ComboBox (instance of the class
CTTComboBox); to enable/disable the tool-tip, you need to perform the
SetToolTipp function before creating or subclassing the ComboBox; for details, see the attached demo project.
- Use the
SetToolTipDelay function to set up the appropriate delay time for showing the tool-tip window.
As mentioned above, by default, tool-tip is allowed, means
TRUE; see the code sample given below:
if (m_isEnableTool == TRUE)
We have called the
CreateTooltipWnd function to create a tool-tip window. (Note: all the ComboBoxes with the same class
CTTComboBox share a tool-tip window.) Now, we have to install a hook for subclassing the list-box and the edit-box portion of the ComboBox, see the
InstallHookForListboxAndEditbox function given below:
cbi.cbSize = sizeof(COMBOBOXINFO);
m_rcButton = cbi.rcButton;
m_hWndList = cbi.hwndList;
WNDPROC oldListWndProc = (WNDPROC)::SetWindowLong(cbi.hwndList,
m_hWndEdit = cbi.hwndItem;
WNDPROC oldEditWndProc = (WNDPROC)::SetWindowLong(cbi.hwndItem,
GetComboBoxInfo function gets the handles to the list-box and the edit-box, then the
SetWindowLong function creates the list-box and the edit-box subclasses, causing the system to call the new window procedure instead of the previous one, a trick, that's all previous (old) window procedures have been added to the map. Later, we will reuse the old window procedure in the new window procedure, such as the window procedure -
HookListboxWndProc with the list-box:
LRESULT CALLBACK CTTComboBox::HookListboxWndProc(HWND hWnd,
UINT message, WPARAM wParam, LPARAM lParam)
CListBox* pList = (CListBox*)CWnd::FromHandle(hWnd);
if (message == WM_MOUSEMOVE)
WORD xPos, yPos;
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
CPoint point(xPos, yPos);
m_isEnter = TRUE;
else if (message == WM_MOUSELEAVE)
m_OriginalSel = LB_ERR;
m_isEnter = FALSE;
else if (message == WM_CAPTURECHANGED)
hWnd, message, wParam, lParam);
At the end of the function, we reuse the old window procedure by calling the
CallWindowProc function from the map like a chain of window procedures. Some of the messages have been reprocessed for the list-box. While processing the
HandleListboxMouseMove function determines whether or not the tool-tip window has to be shown/hidden, and the
OnTrackMouseEvent function tracks the mouse event messages
WM_MOUSELEAVE, that reset the original selection of the list-box when firing up
WM_MOUSELEAVE. Waiting..., the
WM_MOUSELEAVE message takes a continuous place, but the mouse cursor will still be above the list-box, actually, the mouse cursor will be above the tool-tip window when the tool-tip window shows up, think over? So we must capture the list-box to prevent this, to release the mouse capture only when the tool-tip has been hidden.
The ComboBox with owner DropList or DropDown style has a little trouble: when the mouse capture is released, the list-box becomes invisible. So, I have to hold the
WM_CAPTURECHANGED and ignore the message...
You are allowed to use it for free and further modify it according to your needs.
- 27th Sep, 2006.
There are two extra features for the class
CTTCombobox, it now supports these features:
- Allows that you align the listbox by the three modes
CTTCombobox::alignMiddle, using the function
SetAlignStyle to do this thing.
- To disable or enable any items in a combobox, you only simply perform the function
SetDisabledItem. Note: that's not effective when the combobox does not have the
CBS_OWNERDRAWFIXED style, so I suggest you should set the style. There are three methods to gain the style
- You directly check the style for the combobox in the resource.
- If the combobox was created dynamically, then you should do the thing in
OnCreate(LPCREATESTRUCT lpCreateStruct). Usually, you write the code
lpCreateStruct->style |= CBS_OWNERDRAWFIXED | CBS_HASSTRINGS; as the first line in the function
- If the combobox was subclassed dynamically, then you add the code:
ModifyStyle(0, CBS_OWNERDRAWFIXED | CBS_HASSTRINGS); as the first line in
- 8th June, 2005.
Thanks d3m0n, for finding out some bugs in the control. I have fixed all the bugs as follows:
- Hover over the ComboBox and the tool tip appears. Then while the tool tip is still visible, click the arrow to expand the ComboBox. The dropdown list appears and then disappears immediately.
- While the tool tip is visible, nothing can receive the focus. E.g., try clicking the Cancel button while the tool tip is visible.
- The size of the tool tip is sometimes too big, e.g., hover over the ListBox, wait for the tool tip to appear and disappear, now move the mouse out of the ListBox. Now move it into the edit box. The size of the tool tip is really too big.
- 21st July, 2011.
The updated source and demo projects now support the X64 platform and Unicode version compilation for all platforms (Win32 and X64), and a few minor issues have been fixed. The demo project gives two project solutions respectively for VC6.0 and VS2005. Naturally, you can upgrade the solution with VS2008/VS2010.
- 19th November 2011
There is a new function -
SetTipText(int nIndex, LPCTSTR pszTipText). The function gives a customized method to setup tip text for a specified item. Note: this will force the display of the tip text, and if the customized tip text is no longer needed for that item, you're responsible to call the function again and pass