CWnd с прозрачным фоном

Я хотел бы создать класс на основе CWnd, который представит элемент управления с прозрачным фоном.

Для меня нет ничего сложного в создании элемента управления и отображении его содержимого на прозрачном фоне, если содержимое статично.

Проблема в том, когда я хочу создать элемент управления с изменением содержимого. Потому что я не знаю, как стереть содержимое элемента управления с фона родителя (который в общем случае может быть не просто сплошным цветом).

Поэтому цель, которую я хочу достичь, - это стереть элемент управления перед тем, как нарисовать его содержимое, так как элемент управления никогда не существовал (могут появиться родительские и, возможно, другие элементы управления), а затем нарисовать элемент управления в этом месте.

3 ответа

Решение

Ответ Roel хорош, если вы хотите создать окно верхнего уровня. Если вам нужно создать дочернее окно (что должно быть в случае, если вы создаете элемент управления), вы не можете использовать WS_EX_LAYERED (я думаю, что это изменилось с Windows 8 на).

Самый простой трюк - нарисовать родителя в качестве фона управления. Таким образом, в OnEraseBkgnd вы можете добавить этот код:

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

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

Не уверен, что глобальная переменная afxGlobalData предназначена только для MFC 2008 Feature Pack. Если вы используете предыдущую версию MFC, вы можете использовать код из 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;

Вы используете WS_EX_LAYERED и API UpdateLayeredWindow(), чтобы нарисовать ваше окно. См. http://msdn.microsoft.com/en-us/library/ms997507.aspx.

Я использовал приведенный ниже код для моего пользовательского статического элемента управления:

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); 
}
Другие вопросы по тегам