我想创建一个基于 CWnd 的类,它将引入一个具有透明背景的控件。
只要内容是静态的,创建控件并使用透明背景绘制其内容对我来说没什么大不了的。
问题是当我想创建一个内容不断变化的控件时。这是因为我不知道如何用父母的背景擦除控件的内容(通常情况下可能不仅仅是纯色)。
所以我想要实现的目标是在绘制其内容之前擦除控件,因为控件从未存在(父控件,并且可能会出现其他控件),而不是在这个地方绘制控件。
我想创建一个基于 CWnd 的类,它将引入一个具有透明背景的控件。
只要内容是静态的,创建控件并使用透明背景绘制其内容对我来说没什么大不了的。
问题是当我想创建一个内容不断变化的控件时。这是因为我不知道如何用父母的背景擦除控件的内容(通常情况下可能不仅仅是纯色)。
所以我想要实现的目标是在绘制其内容之前擦除控件,因为控件从未存在(父控件,并且可能会出现其他控件),而不是在这个地方绘制控件。
如果你想创建一个顶级窗口,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 和 UpdateLayeredWindow() API 来绘制您的窗口。请参阅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);
}