Introduction
A year ago, I posted an MFC control in the article "An Enhanced CCheckComboBox". Many readers asked me to make this control a COM component available from VB or .NET. Another request was to make the addition of new controls as quick as possible. I decided to create an ATL component which contains a collection of combos with checked trees dropdowns. The combos are created dynamically and displayed in 2, 3 or 4 columns.
Using the Code
To use this code, first you will have to build the "QuickFilter
" project in VC++ 6.0 or VC++ .NET. Then, you can run the three demo projects: "Test with VB", "Test with HTML" and "Test with C#".
Example for populating the first combo: (C#)
QF.set_CheckLabel( 0, "Countries:" );
QF.set_Field( 0, "Countries.ID" );
QF.AddFolder( 0, "North America" );
QF.AddString( 0, "USA", 5, ROOT_LEVEL + 2 );
QF.AddString( 0, "Canada", 6, ROOT_LEVEL + 2 );
QF.AddFolder( 0, "Europe" );
QF.AddString( 0, "UK", 7, ROOT_LEVEL + 2 );
QF.AddString( 0, "Germany", 8, ROOT_LEVEL + 2 );
QF.AddString( 0, "Russia", 9, ROOT_LEVEL + 2 );
QF.AddFolder( 0, "Asia" );
QF.AddString( 0, "Israel", 10, ROOT_LEVEL + 2 );
QF.CheckAll( 0, true );
Points of Interest
The ComboBox
control is made from an EditBox
, a Button
and a TreeView
. The TreeView
is a child of the desktop window, and is shown or hidden when the user presses the button or the edit of the combo (this behavior is by design). I no longer subclass the parent window of the combo, as I did in the previous article but instead, I use mouse capture and the LostFocus
event to hide the dropdown when needed.
When the user presses the button of the combo, I show the dropdown and I wait the WM_LBUTTONUP
message to capture the mouse. At this point, I know that a click outside my control will have to hide the dropdown. Everything seems to be easy, but there is a problem: the scroll bars of the tree dropdown will not work properly if the mouse is already captured. To handle this situation, we will release the mouse capture just as long as the user uses the scrolls and then recapture the mouse again:
LRESULT CCheckTreeCtrl::OnLButtonDown(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
...
if (hWnd == m_hWnd)
if (GetCapture() == hWnd){
LRESULT result = ::SendMessage( hWnd, WM_NCHITTEST, NULL,
MAKELONG(point.x, point.y));
if ((result == HTVSCROLL) || (result == HTHSCROLL)){
::ReleaseCapture();
m_bScroll = TRUE;
::SendMessage( hWnd, WM_NCLBUTTONDOWN, result,
MAKELONG(point.x, point.y));
}
}
...
}
When the user finishes using the scrollbars, a WM_CAPTURECHANGED
message will be sent. This is where we will capture the mouse again.
LRESULT CCheckTreeCtrl::OnCaptureChanged(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
...
if (IsWindowVisible())
if (lParam == NULL)
if (m_bScroll){
SetCapture();
m_bScroll = FALSE;
}
...
}
The rest is quite straightforward. Enjoy using it!
History
This is the first release.
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.