Enhanced Flat ComboBox control
| Exoware ..... |
Tech Note |
Enhanced Flat ComboBox Control
Eric Hartwell - January, 2000
This article describes enhancements to the Kirk Stowell's Office Style Flat ComboBox control.
- The drop-down arrow can hide until the combo field is active (either
selected or has focus).
- The foreground and background colors of the field may be changed dynamically.
Here is Kirk's original Office Style Flat ComboBox article as of December, 1999:
|
||||||||||
Drop-Down Arrow
Hiding the drop-down arrow is actually straightforward, since the CCJFlatComboBox code already overrides the standard button painting. We add a control switch, m_bHideButton, which tells the control whether to paint the button or not.
void CCJFlatComboBox2::ShowButton(BOOL bShow /*= TRUE*/)
{
m_bHideButton = ! bShow;
}
If the control is inactive, we simply paint over it using the control's background color.
switch (eState)
{
case normal:
rcItem.top -= 1;
rcItem.bottom += 1;
// 991018 Hartwell - hide the button unless selected
if (m_bHideButton)
{
rcItem.left -= 1;
pDC->FillSolidRect(rcItem, m_clrBack);
}
else // Display the button as per original code
{
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_BTNHIGHLIGHT));
rcItem.left -= 1;
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_BTNHIGHLIGHT));
}
break;
We also need to hide the arrow when the control is disabled:
if (!IsWindowEnabled())
{
if (m_bHideButton) // 991019 hide button when disabled
{
rcItem.InflateRect(1, 1, 0, 1); // Cover the remaining button
pDC->FillSolidRect(rcItem, m_clrBack); // .. and hide it
}
ReleaseDC(pDC);
return;
}
Finally, we need to force repaint on MouseOver and on SetFocus, so that the previously hidden button is now displayed.
if (m_bHideButton) Invalidate(); // 19991019 force repaint of button
Text and Background Colors
Dynamically changing the control's colors is a little trickier. The problem here is that Windows paints the edit box and the combo box parts of the control separately:
Q81707 - INFO: WM_CTLCOLOR Processing for Combo Boxes of all Styles
Windows sends a WM_CTLCOLOR message to the parent of a control window to enable the parent to specify the color of the control. ... Windows does not define a notification code that enables an application to change the color of a combo box control. However, Windows sends WM_CTLCOLOR messages to a combo box control that relate to its component parts: one message for the list box portion and, if applicable, another message for the edit control portion. An application can subclass the control to intercept and process these messages.
We set the colors by intercepting the CtlColor message for the combo box, and the reflected OnCtlColor message for the edit box. (see TN062: Message Reflection for Windows Controls, and Q148242 - HOWTO: Handle OCM_CTLCOLORxxx Reflected Messages):
// 19991019 Hartwell - this sets the color of the combo box part of the control
HBRUSH CCJFlatComboBox2::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetTextColor(m_clrText);
pDC->SetBkColor(m_clrBack);
return(m_brBack); // ctl bkgnd
}
// 19991019 Hartwell - this sets the color of the edit box part of the control
HBRUSH CCJFlatComboBox2::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
return(CtlColor(pDC, nCtlColor));
}
We also add methods to set the colors dynamically. Note that changing the background color requires creating a new brush.
void CCJFlatComboBox2::SetTextColor(COLORREF cColor)
{
m_clrText = cColor;
}
void CCJFlatComboBox2::SetBackColor(COLORREF cColor)
{
m_clrBack = cColor;
m_brBack.DeleteObject();
m_brBack.CreateSolidBrush( m_clrBack );
}
Revisions:
- January, 2000 - Initial version
This
control easily gives your application the Flat Look that is seen in the
Microsoft office products. To use the control, simply add the files