领导要求制作一个透明的按钮。
我重写了CButton类,在擦除背景消息里面加了如下代码:
BOOL CTransBT::OnEraseBkgnd(CDC* pDC)
{
if(!m_bHasErased)
{
CRect rc;
GetClientRect(&rc);
ClientToScreen(&rc);
CWnd *wndParent=GetParent();
CDC *parentDC=wndParent->GetDC();
wndParent->ScreenToClient(&rc);
CDC memDC;
memDC.CreateCompatibleDC(parentDC);
CBitmap *oldbmp=memDC.SelectObject(&m_bmpBG); //memDC.BitBlt(0,0,rc.Width(),rc.Height(),parentDC,rc.left,rc.top,SRCCOPY);
wndParent->SendMessage(WM_PRINTCLIENT,(WPARAM)memDC.m_hDC,PRF_CLIENT); memDC.SelectObject(oldbmp);
wndParent->ReleaseDC(parentDC);
m_bHasErased=TRUE;
}
return CButton::OnEraseBkgnd(pDC);
}
m_bmpBG里面保存了按钮下面的对话框内容,然后在OnPaint里面用如下代码进行重绘:
void CTransBT::OnPaint()
{
CPaintDC dc(this); // device context for painting
CBrush brush;
brush.CreatePatternBrush(&m_bmpBG);
CRect rc;
GetClientRect(&rc);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
memDC.FillRect(&rc,&brush);
dc.BitBlt(0,0,rc.Width(),rc.Height(),&memDC,0,0,SRCCOPY);
memDC.DeleteDC();
}
问题:实际运行时显示在按钮上面的不是按钮下面对话框相应地方的图片背景,而是对话框下面和按钮位置相对应地方的背景。请问这个问题如何解决?谢谢!
我重写了CButton类,在擦除背景消息里面加了如下代码:
BOOL CTransBT::OnEraseBkgnd(CDC* pDC)
{
if(!m_bHasErased)
{
CRect rc;
GetClientRect(&rc);
ClientToScreen(&rc);
CWnd *wndParent=GetParent();
CDC *parentDC=wndParent->GetDC();
wndParent->ScreenToClient(&rc);
CDC memDC;
memDC.CreateCompatibleDC(parentDC);
CBitmap *oldbmp=memDC.SelectObject(&m_bmpBG); //memDC.BitBlt(0,0,rc.Width(),rc.Height(),parentDC,rc.left,rc.top,SRCCOPY);
wndParent->SendMessage(WM_PRINTCLIENT,(WPARAM)memDC.m_hDC,PRF_CLIENT); memDC.SelectObject(oldbmp);
wndParent->ReleaseDC(parentDC);
m_bHasErased=TRUE;
}
return CButton::OnEraseBkgnd(pDC);
}
m_bmpBG里面保存了按钮下面的对话框内容,然后在OnPaint里面用如下代码进行重绘:
void CTransBT::OnPaint()
{
CPaintDC dc(this); // device context for painting
CBrush brush;
brush.CreatePatternBrush(&m_bmpBG);
CRect rc;
GetClientRect(&rc);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
memDC.FillRect(&rc,&brush);
dc.BitBlt(0,0,rc.Width(),rc.Height(),&memDC,0,0,SRCCOPY);
memDC.DeleteDC();
}
问题:实际运行时显示在按钮上面的不是按钮下面对话框相应地方的图片背景,而是对话框下面和按钮位置相对应地方的背景。请问这个问题如何解决?谢谢!
如果时间紧,用下面的凑和一下吧:
::SetWindowLong(m_hWnd, GWL_EXSTYLE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
::SetLayeredWindowAttributes(m_hWnd, 0, 20, LWA_ALPHA);
m_hWnd是一个你希望透明的目标按钮的窗口句柄,
::SetWindowLong(m_hWnd, GWL_EXSTYLE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
::SetLayeredWindowAttributes(m_hWnd, 0, 20, LWA_ALPHA); // 其中20是透明度,设为0即完全透明,100则完全不透明。
OnCtrlColor里,返回(HBRUSH)GetStockObject(NULL_BRUSH);
把Button的WS_CLIPSIBLINGS样式去掉。
在OnEraseBkgnd里,得到按钮在对话框中的位置,然后调用对话框的RedrawWindow函数,把按钮矩形填进去。这样按钮那个位置就会因为对话框的重绘而被擦掉。
BOOL CTransBT::erase(void)
{
//without b, this function will be executed again and again when redraw the parent;
static b = FALSE;
if (b) return TRUE;
b = TRUE; RECT rect;
GetWindowRect(&rect);
GetParent()->ScreenToClient(&rect);
if (!GetParent()->RedrawWindow(&rect)) return FALSE;
b = FALSE;
return TRUE;
}
用这个函数来擦背景,也就不用保存什么位图了。注意那个b的作用。不过我这是偷懒写法,最好不要用static,而是写作类的成员。
最近常常见到你的名字呢!
http://community.csdn.net/Expert/TopicView3.asp?id=5731152
帮帮我…………
也许CE里面无法实现这个效果?
CDC *pTmpDC, int xSource, int ySource, CBitmap *bmMask)
{
CDC tdc;
tdc.CreateCompatibleDC(NULL);
CBitmap *tmpBitmap=tdc.SelectObject(bmMask); pDC->BitBlt(xStart, yStart,width,height,&tdc,xSource,ySource,SRCAND);
pDC->BitBlt(xStart, yStart,width,height,pTmpDC,xSource,ySource,SRCPAINT); tdc.SelectObject(tmpBitmap);
tdc.DeleteDC();}这种方法要先有mask,要显示的位图和mask一样的部分就会变成透明的
感谢楼上的朋友们的关注,谢谢!
参考http://www.codeproject.com/ce/transparent_controls.asp
搞了一下午,终于搞定图片按钮的透明显示谢谢了