I want to display some information on a control with transparent background. I am using a CStatic control and when opening, the control has a transparent background. But when I try to set the desired information in the control, my control loses transparency and it becomes like a basic CStatic control although it has been set to be transparent. I have overridden the OnPaint method from the derived CStatic class named StaticCtrl. Here is the code of the OnPaint method. I don't do anything else. I only override OnPaint.
void StaticCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Where to draw text
CRect clientRect;
GetClientRect(clientRect);
// Get the caption
CString strTitle;
GetWindowText(strTitle);
// Get the font
CFont *pFont, *pOldFont;
pFont = GetFont();
pOldFont = dc.SelectObject(pFont);
DWORD dwStyle = GetStyle(), dwText = 0;
// Map "Static Styles" to "Text Styles"
#define MAP_STYLE(src, dest)
if(dwStyle & (src)) dwText |= (dest)
#define NMAP_STYLE(src, dest)
if(!(dwStyle & (src))) dwText |= (dest)
MAP_STYLE(SS_RIGHT, DT_RIGHT);
MAP_STYLE(SS_CENTER, DT_CENTER);
MAP_STYLE(SS_CENTERIMAGE, DT_VCENTER | DT_SINGLELINE);
MAP_STYLE(SS_NOPREFIX, DT_NOPREFIX);
MAP_STYLE(SS_WORDELLIPSIS, DT_WORD_ELLIPSIS);
MAP_STYLE(SS_ENDELLIPSIS, DT_END_ELLIPSIS);
MAP_STYLE(SS_PATHELLIPSIS, DT_PATH_ELLIPSIS);
NMAP_STYLE(SS_LEFTNOWORDWRAP | SS_CENTERIMAGE |
SS_WORDELLIPSIS | SS_ENDELLIPSIS |
SS_PATHELLIPSIS, DT_WORDBREAK );
// Set transparent background
dc.SetBkMode(TRANSPARENT);
// Draw the text
if(GetDlgCtrlID() == IDC_STATIC_CANCEL)
dc.SetTextColor(RGB(255, 0, 0));
if(GetDlgCtrlID() == IDC_CONNECTIONTXT ||
GetDlgCtrlID() == IDC_RATETXT)
dc.SetTextColor(RGB(250, 100, 0));
if(GetDlgCtrlID() == IDC_PERCENT ||
GetDlgCtrlID() == IDC_REMAINING ||
GetDlgCtrlID() == IDC_TIMETXT)
dc.SetTextColor(RGB(250, 100, 0));
dc.DrawText(strTitle, clientRect, dwText);
// Select old font
dc.SelectObject(pOldFont);
}
Solution: If you have changed the CDialog background color, you will notice that CStatic & some other controls' background colors still show as the system default COLOR_BTNFACE color. To handle this issue, just make the controls' background transparent so it takes up the color of the dialog's background. Use something like this in your subclassed CDialog's OnCtlColor() event handler to make the background of all static text controls on the dialog transparent. This code considers CMyDialog was derived from CDialog.:
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
CBrush m_brHollow = m_brHollow.CreateStockObject(HOLLOW_BRUSH);
if (nCtlColor == CTLCOLOR_EDIT) {
pDC->SetTextColor(RGB(0, 0, 0)); // text color
pDC->SetBkMode(TRANSPARENT); // background mode
hbr = m_brHollow; // return NULL brush
}
return hbr;
}
If you have painted your dialog background with WHITE, CMyDialog::OnCtlColor() I posted above works fine with CStatic controls on the dialog. But if you have a CSliderCtrl control on the dialog, you'll see that the code above makes the background color of the CSliderCtrl control pitch BLACK.
A work-around is simply to return a handle to a WHITE brush instead of a NULL brush like the code below. This code snippet considers CMyDialog was derived from CDialog & the dialog background was painted white by overriding the CDialog::OnEraseBkgnd() method.
HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
CBrush m_brBgColor;
// dialog background WHITE
m_brBgColor.CreateSolidBrush(RGB(255, 255, 255));
if (nCtlColor == CTLCOLOR_EDIT) {
pDC->SetTextColor(RGB(0, 0, 0)); // text color
pDC->SetBkMode(TRANSPARENT); // background mode
hbr = m_brBgColor; // return WHITE brush
}
return hbr;
}
Refer this.