Mfc CComboBoxEx - How to change the background color - c++

I have a class that is derived from CComboBoxEx and I'm trying to change the background color. I was thinking that it would work like a ComboBox (using the SetBkColor function), but it doesn't change the background color.
Here's what I have tried :
BEGIN_MESSAGE_MAP(CMyComboBoxEx, CComboBoxEx)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
void CMyComboBoxEx::SetBkColor(COLORREF backgroundColor)
{
m_backgroundColor = backgroundColor;
m_brBkgnd.DeleteObject();
m_brBkgnd.CreateSolidBrush(backgroundColor);
}
HBRUSH CMyComboBoxEx::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH brush = __super::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkColor(RGB(255,0,0));
return brush;
}
I've tried with OnEraseBkgnd() too and it didn't worked either.
Do I need to subclass a derived CComboBox class and set the background color in that class?
Thx.

The problem here is that WM_CTLCOLOR messages are sent to the parent window (dialog box, probably) of your combo control, not to the control itself; also, in the case of the drop-down 'list-box' part of the combo, this message is not sent (as the dialog doesn't need to draw it unless the control has been activated).
The way I have achieved what you want is by making the control owner-draw and then (manually) drawing each item in the list.
First, you need to add the CBS_OWNERDRAWFIXED style to your control in the .rc/.rc2 script; like this, for a typical combo:
COMBOBOX IDC_IGONG, 224, 68, 52,120,
CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED | WS_VSCROLL | WS_TABSTOP
Then, you need to add ON_WM_DRAWITEM() to the message map for your dialog class, and override its OnDrawItem() member. Note that the message is sent once for each item in the drop-down list, when the list is made visible by user-action:
void MyDialog::OnDrawItem(int nIDCtl, DRAWITEMSTRUCT *pDIS)
{
switch (pDIS->CtlType) { // You can switch on the ID if it's only one combo!
case ODT_COMBOBOX:
DrawDropDownBox(this, nIDCtl, pDIS);
break;
default:
CDialogEx::OnDrawItem(nIDCtl, pDIS);
break;
}
}
The DrawDropDownBox() does all the hard work:
void MyDialog::DrawDropDownBox(CWnd *box, int nID, DRAWITEMSTRUCT *pDIS)
{
CComboBox *pCBC = dynamic_cast<CMyComboBoxEx *>(box->GetDlgItem(nID));
if (pCBC == nullptr) return; // Skip if we can't get handle to the control
CDC *pDC = CDC::FromHandle(pDIS->hDC);
wchar_t buffer[4096]; // Or just char if you ain't using Unicode
if (pCBC->GetLBText(int(pDIS->itemID), buffer) == CB_ERR) return; // Maybe called during WM_DELETEITEM
int dcSave = pDC->SaveDC(); // Save DC state for later restoration
CPen pen(PS_SOLID, 0, ListColor); // ListColor is COLORREF for your desired b/g
if (pDIS->itemState & ODS_DISABLED) {
pDC->SelectStockObject(NULL_PEN);
pDC->SelectObject(BackBrush); // A CBrush for disabled: defined/created elsewhere
pDC->SetBkMode(TRANSPARENT);
}
else {
pDC->SelectObject(&pen);
pDC->SelectObject(ListBrush); // A CBrush that draws your desired b/g
pDC->SetBkMode(OPAQUE);
}
CRect rc(pDIS->rcItem); pDC->Rectangle(&rc); // This draws the b/g
if (pDIS->itemState & ODS_DISABLED) {
pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
}
else if (pDIS->itemState & ODS_SELECTED) { // Use Windows defaults if selected...
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
}
else {
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
pDC->SetBkColor(ListColor); // Custom b/g color
}
unsigned format = DT_SINGLELINE | DT_VCENTER; // You desired text alignment
pDC->DrawText(CString(buffer), rc, format);
pDC->RestoreDC(dcSave); // Restore DC's saved state...
pDC->Detach(); // ...then 'release it'
return;
}
The code shown handles both disabled combos and selected items in the list; you could possibly skip some of these, if you want to simplify the operation.
Feel free to ask for further explanation and/or clarification.

If it's all about just changing Bk color of the control, then you have to handle WM_CTLCOLOR message in control's parent window:
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID() == IDC_MY_CONTROL)
{
pDC->SetBkColor(RGB(0, 0, 0)); //Black color
hbr = m_hbrBlack; //Black brush.
}
return hbr;
}
Otherwise, you have to draw your control totally yourself in your derived class, with CBS_OWNERDRAWFIXED or CBS_OWNERDRAWVARIABLE style, which is way more complicated, but ofc possible.

I'm surprised that all the answers you've got so far suggest either handling WM_CTLCOLOR in parent window or use one of OWNERDRAW styles.
Handling WM_CTLCOLOR in parent window means you'll need to duplicate that code in each parent window's class where you'll use such combobox. This is obviously a bad solution if you want to use combobox more than once.
Adding OWNERDRAW style may have impact on other existing controls that you'd like to subclass and you may need to handle additional problems. That's also far from a sinmple solution.
Fortunately, there's another way to solve it - use Message Reflection. And all you need to do is to add ON_WM_CTLCOLOR_REFLECT() entry to the message map and CtlColor handler.
In case of combobox control I'd do it like this:
MyComboBoxEx.h
class CMyComboBoxEx : public CComboBoxEx
{
public:
CMyComboBoxEx();
virtual ~CMyComboBoxEx();
protected:
CBrush m_BkBrush;
DECLARE_MESSAGE_MAP()
public:
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
MyComboBoxEx.cpp
CMyComboBoxEx::CMyComboBoxEx()
{
m_BkBrush.CreateSolidBrush(RGB(0, 255, 0));
}
CMyComboBoxEx::~CMyComboBoxEx()
{
}
BEGIN_MESSAGE_MAP(CMyComboBoxEx, CComboBoxEx)
ON_WM_CTLCOLOR_REFLECT()
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
HBRUSH CMyComboBoxEx::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkColor(RGB(0, 255, 0));
return m_BkBrush;
}
HBRUSH CMyComboBoxEx::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
return CtlColor(pDC, nCtlColor);
}
Here's how such combobox looks:
If you want to have custom color for borders and glyph then you need to handle WM_PAINT yourself.

Related

How can I define new colors in a CPropertySheet?

I'm trying to define new colors in some regions of a CPropertySheet (mfc libaries). What I've tried is to overload OnCtlColorand define a new background color. This methods works well but it doesn't colorize the region I want.
In the next image you can see what I get with my method.
Image of the control
In this image you can see 4 colorized regions:
Red: Region that I can colorize using OnCtlColor
Dark Gray and black: Region that I can colorize using OnCtlColor
of the object CPropertyPage
Light Gray (Indicated with a blue arrow): Region I want to colorize
White margin: Region I want to colorize too.
I don't know what to do to colorize all regions using this libraries or using any Customizable object. Any help will be appreciated.
Thanks!
Update 1
After the answer of Adrian it looks like this
However, there's still one region we cannot colorize.
Answer
Before trying a lot of combinations, I've done the next two objects which allows me to define the colors I need. You can find all source code behind. The result of this code can be checked in this picture
PropertyPage
Header
class CustomPropertyPage : public CPropertyPage
{
public:
static const COLORREF PROPERTYPAGE_BACKGROUND = RGB(68, 74, 80);
DECLARE_MESSAGE_MAP()
public:
CustomPropertyPage(UINT nIDTemplate);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
cpp
CustomPropertyPage::CustomPropertyPage(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
{
}
BEGIN_MESSAGE_MAP(CustomPropertyPage, CPropertyPage)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
HBRUSH CustomPropertyPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (pWnd->GetDlgCtrlID() != 0)
return CPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
HBRUSH hbr = CreateSolidBrush(PROPERTYPAGE_BACKGROUND_COLOR);
return hbr;
}
PropertySheet
Header
class CustomPropertySheet : public CPropertySheet
{
DECLARE_MESSAGE_MAP()
public:
CustomPropertySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage);
virtual BOOL OnInitDialog();
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
private:
void Draw_Background(CDC *pDC);
};
cpp
CustomPropertySheet::CustomPropertySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
}
BEGIN_MESSAGE_MAP(CustomPropertySheet, CPropertySheet)
ON_WM_CTLCOLOR()
ON_WM_DRAWITEM()
END_MESSAGE_MAP()
BOOL CustomPropertySheet::OnInitDialog()
{
BOOL answer = CPropertySheet::OnInitDialog();
CWnd* pTab = GetDlgItem(AFX_IDC_TAB_CONTROL);
SetWindowLongPtr(pTab->m_hWnd, GWL_STYLE, GetWindowLongPtr(pTab->m_hWnd, GWL_STYLE) | TCS_OWNERDRAWFIXED);
pTab->RedrawWindow();
return answer;
}
void CustomPropertySheet::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (nIDCtl == AFX_IDC_TAB_CONTROL)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
Draw_Background(pDC);
CRect rc(lpDrawItemStruct->rcItem);
rc.bottom += 1;
pDC->FillSolidRect(rc, CEasyPropertyPage::PROPERTYPAGE_BACKGROUND);
pDC->SetTextColor(GENERIC_TEXT_COLOR);
pDC->SetBkMode(TRANSPARENT);
char text[256];
TCITEM tci = { TCIF_TEXT | TCIF_STATE, 0, 0, text, 255, -1, 0 };
HWND tcw = ::GetDlgItem(m_hWnd, nIDCtl);
int i, tic = int(::SendMessage(tcw, TCM_GETITEMCOUNT, 0, 0));
for (i = 0; i < tic; ++i)
{
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
CRect tir;
::SendMessage(tcw, TCM_GETITEM, WPARAM(i), LPARAM(&tci));
::SendMessage(tcw, TCM_GETITEMRECT, WPARAM(i), LPARAM(&tir));
pDC->DrawText(text, tir, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
}
else CPropertySheet::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
HBRUSH CustomPropertySheet::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (pWnd->GetDlgCtrlID() != 0)
return CPropertySheet::OnCtlColor(pDC, pWnd, nCtlColor);
HBRUSH hbr = CreateSolidBrush(GENERIC_BACKGROUND_COLOR);
return hbr;
}
void CustomPropertySheet::Draw_Background(CDC* pDC)
{
CRect rect; this->GetClientRect(rect);
pDC->FillSolidRect(rect, GENERIC_BACKGROUND_COLOR);
rect.DeflateRect(0, 20, 0, 0);
pDC->FillSolidRect(rect, GENERIC_BORDER_COLOR);
}
To customize the light gray area (which is the embedded tab control) you need to override the OnDrawItem method in your class that is derived from CPropertySheet and do your custom drawing for the control with the AFX_IDC_TAB_CONTROL identifier. Something like this:
void MyPropertySheet::OnDrawItem(int nID, LPDRAWITEMSTRUCT pDIS)
{
if (nID == AFX_IDC_TAB_CONTROL) {
CDC* pDC = CDC::FromHandle(pDIS->hDC);
CRect rc(pDIS->rcItem); rc.bottom += 1;
pDC->FillSolidRect(rc, RGB(255, 0, 0)); // Or whatever b/g/ colour you want
pDC->SetTextColor(RGB(0,0,0)); // Or whatever text colour you want
pDC->SetBkMode(TRANSPARENT);
char text[256];
TCITEM tci = { TCIF_TEXT | TCIF_STATE, 0, 0, text, 255, -1, 0 };
CRect tir;
HWND tcw = ::GetDlgItem(m_hWnd, nID);
int i, tic = int(::SendMessage(tcw, TCM_GETITEMCOUNT, 0, 0));
for (i = 0; i < tic; ++i) {
::SendMessage(tcw, TCM_GETITEM, WPARAM(i), LPARAM(&tci));
::SendMessage(tcw, TCM_GETITEMRECT, WPARAM(i), LPARAM(&tir));
if (pDIS->itemState & ODS_SELECTED)
pDC->DrawText(text, tir, DT_CENTER |DT_VCENTER | DT_SINGLELINE);
}
pDC->Detach();
}
else { // Pass other stuff to the base class
CPropertySheet::OnDrawItem(nID, pDIS);
}
return;
}
Of course, be sure to add ON_WM_DRAWITEM() to the message map!
EDIT: You must also explicitly set the style of the embedded tab control to include TCS_OWNERDRAWFIXED. You can do this in the OnInitDialog override for your class.
EDIT 2: I have a slightly better way to get a pointer to the tab control, now! Also, I have added a few lines of code that act as a "cheat" to address the remaining area that needs to be coloured - by expanding the tabs to fit the width of the underlying control ...
BOOL MyPropertySheet::OnInitDialog()
{
BOOL answer = CPropertySheet::OnInitDialog(); // Call base class first!
// ... whatever other stuff you may wish to do
// CWnd* pTab = GetDlgItem(AFX_IDC_TAB_CONTROL);
CTabCtrl* pTab = GetTabControl(); // This is a bit clearer than above line!
// The following 4 lines comprise a 'first stab' at fixing the remaining issue:
CRect rcTab; pTab->GetWindowRect(&rcTab);
int nItems = pTab->GetItemCount();
int border = GetSystemMetrics(SM_CXEDGE) * 2;
pTab->SetMinTabWidth((rcTab.Width() - border) / nItems);
// ...
SetWindowLongPtr(pTab->m_hWnd, GWL_STYLE, GetWindowLongPtr(pTab->m_hWnd, GWL_STYLE) | TCS_OWNERDRAWFIXED);
pTab->RedrawWindow();
return answer;
}
Feel free to ask for further clarification and/or explanation.

How to set textcolor of menu item in mfc

I want to change text color of menu in mfc. I have searched a lot but didn't got a proper solution. Finally I was trying to use OnCtlColor which I generally use for setting the color of static text control. But I am confused here how to do the same for menu items because pWnd->GetDlgCtrlID() dont work on menu.My menu item id is ID_MENU_ITEM. My query is what should i write at "?" to get my job done. And if my approach is wrong please suggest me good alternative.
HBRUSH CMyClass::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr;
if ( ? == ID_MENU_ITEM)
{
pDC->SetTextColor(RGB(255, 0, 0));
hbr = (HBRUSH)m_whitebrush;
return hbr;
}
}

Coloring the entire background of an MFC static label

This Answer is really great if you want to change the background color of a "conventional" text label. But what if you want to put a border around that text label and expand its size so that the text is swimming in a veritable sea of color? It only paints the text background in the required color, and leaves the rest of the expanded control with the standard button face. How can one make the color consistent across the entire control?
Note: The attractive feature (to me anyway) about the above answer is that it makes use of OnCtlColor(), which provides a pointer to the CWnd control concerned. So there is no need to create a subclass of CStatic to handle the color change. An answer that avoids creating such a subclass would be preferred.
I'm not very sure about OP's Note section. Still posting this code for his help.
HBRUSH CSampleDlg::OnCtlColor(CDC* pDC, CWnd *pWnd, UINT nCtlColor)
{
switch (nCtlColor)
{
case CTLCOLOR_STATIC:
{
CRect rcWindow(0, 0, 220, 40);
//::GetWindowRect(pWnd->GetSafeHwnd(), &rcWindow);
pDC->FillSolidRect(rcWindow, RGB(49, 49, 49));
pDC->SetTextColor(RGB(255, 255, 255));
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
default:
{
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
}
}
You can make the static control invisible in the resource editor then paint it from CMyDialog.
void CMyDialog::OnPaint()
{
CDialog::OnPaint();
paintstatic(IDC_STATIC1);
}
void CMyDialog::paintstatic(int id)
{
CClientDC dc(this);
CRect rc;
CWnd *child = GetDlgItem(id);
child->GetWindowRect(&rc);
CPoint offset(0, 0);
ClientToScreen(&offset);
rc.OffsetRect(-offset);
dc.FillSolidRect(rc, RGB(0, 255, 128));
CFont *font = GetFont();
dc.SelectObject(font);
CString text;
child->GetWindowText(text);
dc.DrawText(text, rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

Change Color of read only CEdit control Artifacts and Text Highlighting issue

I have an Edit control that is read only that has text in it. I would like to switch the default gray background to white but have been having limited luck. In my first go, I was executing the following code during initialization of the dialog:
CEdit *m_ctrlEditOne = (CEdit*) GetDlgItem(IDC_EDIT1);
CDC *m_ctrlEEditWee = m_ctrlEditOne->GetDC();
m_ctrlEEditWee->SetBkColor(RGB(255,0,0));
Invalidate(true);
Another solution I tried was:
HBRUSH CTestingDlg::OnCtlColor(CDC* pDC, CWnd *pWnd, UINT nCtlColor)
{
if (pWnd->GetStyle() & ES_READONLY)
//if(pDC->GetRuntimeClass == & ES_READONLY)
{
switch (nCtlColor)
{
case CTLCOLOR_STATIC:
pDC->SetBkColor(RGB(255,255,255));
return (HBRUSH)GetStockObject(NULL_BRUSH);
default:
//return NULL;
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
}
//return NULL;
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
In the screenshot below, you can see that the text is inserted after the fact (this is what needs to happen) and appears highlighted in blue - I have no idea where to begin on how to make it just appear as normal, non-highlighted text. When clicking on it, it appears normally. In the bottom left corners of each edit control, one can see a square which should not be appearing there. Also, you can see some artifacts of what looks like to be a combo box dropdown selection appearing in the larger boxes.
I would appreciate any pointers on how to get rid of the artifacts and fix the highlighting issue with inserted text.
I do as shown below. It will change the background of the read only edit control IDC_EDIT1 to white. This is a copy-paste straight out of one of my projects.
m_whitebrush is a private member of CTestOnCtlClorDlg of type HBRUSH and must be initialized to NULL in the constructor of CTestOnCtlClorDlg.
HBRUSH CTestOnCtlClorDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
int id = pWnd->GetDlgCtrlID( ) ;
if (id == IDC_EDIT1)
{
pDC->SetTextColor(RGB(0, 0, 0));
pDC->SetBkColor(RGB(255,255,255));
if (!m_whitebrush)
m_whitebrush = CreateSolidBrush(RGB(255,255,255)) ;
hbr = m_whitebrush ;
}
return hbr;
}
void CTestOnCtlClorDlg::OnDestroy()
{
CDialog::OnDestroy();
if (m_whitebrush !=NULL)
{
DeleteObject(m_whitebrush) ;
m_whitebrush = NULL ;
}
}

MFC - change text color of a cstatic text control

How do you change the text color of a CStatic text control? Is there a simple way other that using the CDC::SetTextColor?
You can implement ON_WM_CTLCOLOR in your dialog class, without having to create a new CStatic-derived class:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
//{{AFX_MSG_MAP(CMyDialog)
ON_WM_CTLCOLOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd *pWnd, UINT nCtlColor)
{
switch (nCtlColor)
{
case CTLCOLOR_STATIC:
pDC->SetTextColor(RGB(255, 0, 0));
return (HBRUSH)GetStockObject(NULL_BRUSH);
default:
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
}
Notice that the code above sets the text of all static controls in the dialog. But you can use the pWnd variable to filter the controls you want.
unfortunately you won't find a SetTextColor method in the CStatic class. If you want to change the text color of a CStatic you will have to code a bit more.
In my opinion the best way is creating your own CStatic-derived class (CMyStatic) and there cacth the ON_WM_CTLCOLOR_REFLECT notification message.
BEGIN_MESSAGE_MAP(CMyStatic, CStatic)
//{{AFX_MSG_MAP(CMyStatic)
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
HBRUSH CColorStatic::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetTextColor(RGB(255,0,0));
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
Obviously you can use a member variable and a setter method to replace the red color (RGB(255,0,0)).
Regards.
Just a follow up to the painting issue (a transparent background), which caused by *return (HBRUSH)GetStockObject(NULL_BRUSH);*
Easy change as below:
HBRUSH hBrush = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_STATIC &&
pWnd->GetSafeHwnd() == GetDlgItem(XXX)->GetSafeHwnd()
) pDC->SetTextColor(RGB(255, 0, 0));
return hBrush;
Hope this helps.
From the Answers given here and other places, it was not obvious how to create a derived class to be used instead of CStatic that handles coloring itself.
So following is what works for me, using MSVS 2013 Version 12.0.40629.00 Update 5. I can place a "Static Text"-control in the resource editor, then replace the type of the member variable with TColorText.
In the .h-file:
class TColorText : public CStatic
{
protected:
DECLARE_MESSAGE_MAP( )
public:
// make the background transparent (or if ATransparent == true, restore the previous background color)
void setTransparent( bool ATransparent = true );
// set background color and make the background opaque
void SetBackgroundColor( COLORREF );
void SetTextColor( COLORREF );
protected:
HBRUSH CtlColor( CDC* pDC, UINT nCtlColor );
private:
bool MTransparent = true;
COLORREF MBackgroundColor = RGB( 255, 255, 255 ); // default is white (in case someone sets opaque without setting a color)
COLORREF MTextColor = RGB( 0, 0, 0 ); // default is black. it would be more clean
// to not use the color before set with SetTextColor(..), but whatever...
};
in the .cpp-file:
void TColorText::setTransparent( bool ATransparent )
{
MTransparent = ATransparent;
Invalidate( );
}
void TColorText::SetBackgroundColor( COLORREF AColor )
{
MBackgroundColor = AColor;
MTransparent = false;
Invalidate( );
}
void TColorText::SetTextColor( COLORREF AColor )
{
MTextColor = AColor;
Invalidate( );
}
BEGIN_MESSAGE_MAP( TColorText, CStatic )
ON_WM_CTLCOLOR_REFLECT( )
END_MESSAGE_MAP( )
HBRUSH TColorText::CtlColor( CDC* pDC, UINT nCtlColor )
{
pDC->SetTextColor( MTextColor );
pDC->SetBkMode( TRANSPARENT ); // we do not want to draw background when drawing text.
// background color comes from drawing the control background.
if( MTransparent )
return nullptr; // return nullptr to indicate that the parent object
// should supply the brush. it has the appropriate background color.
else
return (HBRUSH) CreateSolidBrush( MBackgroundColor ); // color for the empty area of the control
}
Very helpful.
https://msdn.microsoft.com/de-de/library/0wwk06hc.aspx
Alike to
HBRUSH hBrush = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_STATIC &&
pWnd->GetSafeHwnd() == GetDlgItem(XXX)->GetSafeHwnd()
) pDC->SetTextColor(RGB(255, 0, 0));
return hBrush;
I believe you can't return nullptr for a HBRUSH rather (HBRUSH)GetStockObject(NULL_BRUSH);