Introduction
During the development of a larger application I found myself needing a CCombobox
type control that could have groupings inside of it. I wanted the control to resemble more of a button apparatus but with a drop down that a user could select from...hence the CDropButton
class was created. You may have seen this type of control used before in Microsoft Money. It's an excellent way to group items in a drop list.
The control is quite functional using a CButton
class for the main class, and a CWnd
and a CListbox
for displaying the data. It is completely customizable, with the ability to change colors of just about everything except the scrollbar, which may come later.
It works like a regular CCombobox
except the items are grouped under headers. Headers appear in bold and a distinguishing line. Headers themselves are unselectable and their data is alphabetical. The CDropButton
can be set to either replace the text on the button with a selection or not.
Here's what the default control looks like:
Here's what a custom control could look like (pretty huh?):
The control is very easy to use:
Create a default CDropButton
using the following create:
m_pDropBtn = new CDropButton();
m_pDropBtn->Create("Options", CRect(100,100,280,120), this, ID_DROP_BUTTON);
You can also send in lots of options in the create in order to customize to your preference!
COLORREF crButtonBackgroundColor = RGB(150,0,0);
COLORREF crButtonBackgroundOverColor = RGB(200,50,50);
COLORREF crButtonTxtColor = RGB(255,255,255);
COLORREF crButtonTxtOverColor = RGB(255,255,150);
CFont* pTextFont = NULL;
m_pDropBtn->Create("Options", CRect(300,100,450,120), this, ID_DROP_BUTTON,
crButtonBackgroundColor, crButtonBackgroundOverColor,
crButtonTxtColor, crButtonTxtOverColor, pTextFont);
m_pDropBtn->SetListHeight(200);
m_pDropBtn->SetListWidth(170);
m_pDropBtn->ChangeTitleWithSelection(
false);
In the example above I do not set a font but this is possible, it defaults to 14 point arial. The 'crButtonBackgroundOverColor' parameter makes the button change color when the mouse passes over the control.
After the CDropButton is created you can then get a hold of the list box and set optional properties.
CDropList* pList = m_pDropBtn->GetList();
pList->SetBkColor(crBkListColor);
pList->SetHighlightBkColor(
RGB(255,255,100));
Then add the data. Items in the first group do not have a header. You use the standard CListBox AddString
function to add them.
pList->AddString("Split/Multiple Catagories...");
pList->AddString("Add New Category...");
You can add specific items to a group. You specify the group as the second parameter. The third and forth parameters are optional text colors for that specific item. Every item can have a specific color!
pList->AddString("EXPENSE", 2, RGB(128,0,0), RGB(255,0,0));
pList->AddString("Automobile", 2);
pList->AddString("Health Care", 2);
pList->AddString("Gifts", 2);
pList->AddString("INCOME", 3, RGB(0,128,0), RGB(0,255,0));
pList->AddString("Wages/Salary", 3);
pList->AddString("Retirement Income", 3);
pList->AddString("Other Income", 3);
pList->AddString("SPECIAL", 4, RGB(0,0,128), RGB(0,0,255));
pList->AddString("Transfer", 4);
pList->AddString("Loan Payment", 4);
pList->AddString("Clothing", 2);
The control sends back only one message. It sends you a CM_SELECTION_CHANGED
message to let you know when a selection has changed. To implement it, place the following statement in your message map
ON_MESSAGE(CM_SELECTION_CHANGED, OnSelectionChanged)
Place this line in your header file:
afx_msg LONG OnSelectionChanged(UINT wParam, LONG lParam);
The function to handle this would look something close to this:
LONG CTestView::OnSelectionChanged(UINT wParam, LONG lParam)
{
CDropList* pList;
switch(wParam)
{
case ID_DROP_BUTTON:
pList = m_pDropBtn->GetList();
break;
case ID_DROP_BUTTON2:
pList = m_pDropBtn2->GetList();
break;
}
CString csText;
pList->GetText(pList->GetCurSel(), csText);
AfxMessageBox(csText);
return 1;
}
The
wParam is the ID of the Control that sent the message.
Most all the standard CListBox
functions will work except a few. I have NOT tested this for a multiple selection CListBox
! In my case, I did not need this therefore did not try to account for it. Also InsertString
will not work, the control handles the position of the data items.
RemoveString
does work but a little differently when deleting a header item. When a header item is removed so are all of its children.
Most all of the other standard functions should work (SelectString
, SetCurSel
, etc.) but be aware I did not test ALL of these functions. Be sure to try them out first!
One last thing, horizontal scrolling does not work! I think that it is unnecessary for this control. If you really need it however, simply add the style to the CDropList
.
The code behind CDropButton
should be very easy to follow and easy to modify. If you make changes to the code (like a custom scrollbar) please send me a copy! I'd love to see it!
This was created on Windows 2000 using Visual C++ 6.0.