领导要求制作一个透明的按钮。
我重写了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();
}
问题:实际运行时显示在按钮上面的不是按钮下面对话框相应地方的图片背景,而是对话框下面和按钮位置相对应地方的背景。请问这个问题如何解决?谢谢!

解决方案 »

  1.   

    STButton有settansparent函数,,,直接用
      

  2.   

    很佩服楼主的自己动手丰衣足食的精神,
    如果时间紧,用下面的凑和一下吧:
    ::SetWindowLong(m_hWnd, GWL_EXSTYLE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
    ::SetLayeredWindowAttributes(m_hWnd, 0, 20, LWA_ALPHA);
      

  3.   

    如果你用CButton的话,代码写在重载的OnCreate里面,
    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则完全不透明。
      

  4.   

    这个透明,会透明到什么东西都看不到的程度。
    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,而是写作类的成员。
      

  5.   

    lisunlin0(李林)
    最近常常见到你的名字呢!
    http://community.csdn.net/Expert/TopicView3.asp?id=5731152
    帮帮我…………
      

  6.   

    忘了说明,我的程序是运行在windowsCE里的,按楼上兄弟的建议修改的程序无法编译...
    也许CE里面无法实现这个效果?
      

  7.   

    void DrawBitmap(CDC *pDC, int xStart, int yStart, int width, int height, 
    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一样的部分就会变成透明的
      

  8.   

    用画刷FillRect之前要先根据按钮位置计算一下背景图案原点位置,SetBrushOrgEx,使其画到按钮与背景重合。
      

  9.   

    参考http://www.codeproject.com/ce/transparent_controls.asp已经解决了问题
    感谢楼上的朋友们的关注,谢谢!
      

  10.   

    哈哈
    参考http://www.codeproject.com/ce/transparent_controls.asp
    搞了一下午,终于搞定图片按钮的透明显示谢谢了