最简单的方法是映射WM_ERASEBKGND消息,在消息处理函数中直接return TRUE;这种方法通过不擦除背景实现,故经常会有其他问题,比如文字从带下划线都无下划线的变化中,因为下划线不擦除,故始终有下划线.
以下提供一种贴图的方式实现,即将控件所在位置的背景截图,然后贴在控件表面上,在按钮中测试成功,其他控件类似.以下以自绘的按钮类CToolButton为例.
(1)设置控件的自绘模式,因为要实现贴图,所以只能进行自绘.如果不知道怎么设置自绘,建议先好好去看书.
(2)在控件类中加入成员变量CBitmap m_bmpBk;用于保存背景.
(3)声明成员函数void SetBkBmp(),用于在变量m_bmpBk中保存控件所在位置父窗口截图.
void CToolButton::SetBkBmp()
{
if(m_bmpBk.m_hObject){m_bmpBk.DeleteObject();}
CRect rect;
GetWindowRect(&rect);
GetParent()->ScreenToClient(&rect);
CClientDC clDC(GetParent());
m_bmpBk.CreateCompatibleBitmap(&clDC,rect.Width(),rect.Height());
CDC memDC;
memDC.CreateCompatibleDC(&clDC);
memDC.SelectObject(&m_bmpBk);
memDC.BitBlt(0,0,rect.Width(),rect.Height(),&clDC,rect.left,rect.top,SRCCOPY);
memDC.DeleteDC();
}
(4)重载DrawItem函数,实现将m_bmpBk贴在控件表面与自绘
void CToolButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
CRect rcItem = lpDrawItemStruct->rcItem;
HDC hDC = lpDrawItemStruct->hDC;
CDC dc;
dc.Attach(hDC);
dc.SetBkMode(TRANSPARENT);
if(m_bmpBk.m_hObject)
{
CDC memdc;
memdc.CreateCompatibleDC(&dc);
memdc.SelectObject(m_bmpBk);
dc.BitBlt(0,0,rcItem.Width(),rcItem.Height(),&memdc, 0, 0,SRCCOPY);
memdc.DeleteDC();
}
//以下为自定义的自绘代码
}
(5)在父窗口的OnPaint函数的最后调用控件的SetBkBmp函数.Over!
PS:原想在DrawItem中直接对父窗口截图再贴图,但一直不成功,因为在DrawItem中实现时,父窗口已经被上一次重绘时的控件覆盖.