
Introduction
There are many ways to develop a transparent static control. I like two approaches in particular, because they are simple and they get the job done. When you think about placing a static control with a transparent background on your window, the one important thing you have to consider is, whether the background is static or dynamic. The problem of having a static control changes depending on what is displayed in the background.
Method 1
If the background is static, then the best approach is to make a copy of the area on the parent window behind the static control before it is drawn for the first time, and then simply copy the image back to the parent every time the static control needs to be redrawn. The advantage of this approach is its flicker free display every time the static control is changed.
LRESULT CTransparentStatic2::OnSetText(WPARAM wParam,LPARAM lParam)
{
LRESULT Result = Default();
Invalidate();
UpdateWindow();
return Result;
}
HBRUSH CTransparentStatic2::CtlColor(CDC* pDC, UINT )
{
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
BOOL CTransparentStatic2::OnEraseBkgnd(CDC* pDC)
{
if (m_Bmp.GetSafeHandle() == NULL)
{
CRect Rect;
GetWindowRect(&Rect);
CWnd *pParent = GetParent();
ASSERT(pParent);
pParent->ScreenToClient(&Rect);
CDC *pDC = pParent->GetDC();
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
m_Bmp.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height());
CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY);
MemDC.SelectObject(pOldBmp);
pParent->ReleaseDC(pDC);
}
else
{
CRect Rect;
GetClientRect(Rect);
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
pDC->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(pOldBmp);
}
return TRUE;
}
Method 2
The other approach comes in handy when the parent window's background is dynamic. If the parent window's background is constantly changing then the above approach will not look too nice. So instead of all the copying, what the static control should do is invalidate the area of the parent where the control resides every time its text is changed. This method is much simpler than the one before, but it could flicker if the text is changed at a rapid rate.
LRESULT CTransparentStatic::OnSetText(WPARAM wParam,LPARAM lParam)
{
LRESULT Result = Default();
CRect Rect;
GetWindowRect(&Rect);
GetParent()->ScreenToClient(&Rect);
GetParent()->InvalidateRect(&Rect);
GetParent()->UpdateWindow();
return Result;
}
HBRUSH CTransparentStatic::CtlColor(CDC* pDC, UINT )
{
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
Keep an eye out for a Transparent Edit control and Transparent Listbox.