1
votes

I'd like to create a CWnd based class that will introduce a control with transparent background.

There is no big deal for me to create a control and draw its content with transparent background as long as the content is static.

The problem is when I want to create a control with changing content. It's becaue I don't know how to erase content of control with parent's background (which in general case may not be just a solid color).

So the goal I want to achieve is to erase control before painting its conent as the control was never there (parent, and maybe other controls may appear), and than paint control in this place.

3

3 Answers

4
votes

Roel answer is fine if you want to create a top-level window. If you need to crate a child window (which must be the case if you are creating a control) you cannot use WS_EX_LAYERED (I think this has changed from Windows 8 on).

The easy trick is to draw parent as the control backgroud. So in the OnEraseBkgnd you can add this code:

BOOL uiBarcodeButton::OnEraseBkgnd(CDC* pDC)
{
    CRect rect;
    GetClientRect(rect);

    return afxGlobalData.DrawParentBackground( this, pDC, rect);
}

Not sure if afxGlobalData global variable is just for MFC 2008 Feature Pack. If you are using a previous version of MFCs then you can use the code from DrawParentBackground:

ASSERT_VALID(pDC);
ASSERT_VALID(pWnd);

BOOL bRes = FALSE;

CRgn rgn;
if (rectClip != NULL)
{
    rgn.CreateRectRgnIndirect(rectClip);
    pDC->SelectClipRgn(&rgn);
}

CWnd* pParent = pWnd->GetParent();
ASSERT_VALID(pParent);

// In Windows XP, we need to call DrawThemeParentBackground function to implement
// transparent controls
if (m_pfDrawThemeBackground != NULL)
{
    bRes = (*m_pfDrawThemeBackground)(pWnd->GetSafeHwnd(), pDC->GetSafeHdc(), rectClip) == S_OK;
}

if (!bRes)
{
    CPoint pt(0, 0);
    pWnd->MapWindowPoints(pParent, &pt, 1);
    pt = pDC->OffsetWindowOrg(pt.x, pt.y);

    bRes = (BOOL) pParent->SendMessage(WM_ERASEBKGND, (WPARAM)pDC->m_hDC);

    pDC->SetWindowOrg(pt.x, pt.y);
}

pDC->SelectClipRgn(NULL);

return bRes;
2
votes

You use WS_EX_LAYERED and the UpdateLayeredWindow() API to draw your window. See http://msdn.microsoft.com/en-us/library/ms997507.aspx .

0
votes

I used below code for my custom Static control:

BOOL MyStaticText::OnEraseBkgnd(CDC* pDC)
{
    CRect rect;
    GetClientRect(&rect);
    pDC->SelectObject((HBRUSH)GetStockObject(NULL_BRUSH));
    return pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY); 
}