CButton 重绘(支持PNG图片作为背景)

按钮重绘支持PNG图片作为背景很使用。可以实现按钮一种背景图片,然后鼠标点击按钮,增加一个透明的png边框,也可以修改以下实现鼠标停留在某个按钮上面,改变按钮的状态。

#if !defined(AFX_PICBUTTON_H__4A8AEB90_4455_44B5_B4BE_20B5B77453E1__INCLUDED_)
#define AFX_PICBUTTON_H__4A8AEB90_4455_44B5_B4BE_20B5B77453E1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// PicButton.h : header file
//

#define ALIGN_HORZ      0
#define ALIGN_VERT      1
/////////////////////////////////////////////////////////////////////////////
// CPicButton window
class CPicButton : public CButton
{
// Construction
public:
    CPicButton();

// Attributes
public:
// Operations
public:
    void SetTextColor(COLORREF color) { m_TextColor=color; } 
    void SetBkColor(COLORREF color) { m_BackColor=color; }
    void SetFocusColor(COLORREF color) { m_FocusColor=color; }
    void SetBitmapEx(LPCTSTR lpszFile);
    void SetBitmapEx(UINT nBitmapID);
    void SetBorder(UINT nSet){m_nBorder=nSet;}
    void SetTextAlign(UINT nSet){m_nTextAlign=nSet;}
    void SetIconAlign(UINT nSet){m_nIconAlign=nSet;}
    void SetBackBmp(LPCTSTR lpszFile);
    void SetBackBmp(UINT nNormalID);
    void SetBitmap(UINT nNormalID,UINT nDisableID=0);
    void SetBitmap(LPCTSTR lpszNormal,LPCTSTR lpszDisabled=NULL);
    void SetCheck(int nCheck, BOOL bRepaint = TRUE);
    void SetStatic(BOOL bSet){m_bStatic=bSet;}
    int GetCheck();
    void DeleteObject();
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CPicButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CPicButton();

    // Generated message map functions
protected:
    //{{AFX_MSG(CPicButton)
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg BOOL OnClicked();
    afx_msg void OnCaptureChanged(CWnd *pWnd);
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG
    LRESULT OnSetCheck(WPARAM wParam, LPARAM lParam);
    LRESULT OnGetCheck(WPARAM wParam, LPARAM lParam);
    DECLARE_MESSAGE_MAP()
private:
    COLORREF m_TextColor, m_BackColor,m_FocusColor;
    HBITMAP m_bmpNormal,m_bmpDisabled;
    CBitmap m_bmpBack,m_bmpButton;
    UINT m_nBorder;
    UINT m_nTextAlign,m_nIconAlign;
    int m_nCheck,m_bCheckBox;
    BOOL    m_MouseOnButton,m_bStatic;
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_PICBUTTON_H__4A8AEB90_4455_44B5_B4BE_20B5B77453E1__INCLUDED_)

实现

// PicButton.cpp : implementation file
//

#include "stdafx.h"
#include "PicButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPicButton

CPicButton::CPicButton()
{
    m_TextColor=RGB(255,255,255);
    m_BackColor=RGB(40,40,70);
    m_FocusColor=RGB(255,0,0);
    m_nBorder=BF_RECT;
    m_nTextAlign=DT_CENTER;
    m_nIconAlign=ALIGN_HORZ;
    m_bmpNormal=NULL;
    m_bmpDisabled=NULL;
    m_nCheck=0;
    m_bCheckBox=0;
    m_MouseOnButton=FALSE;
    m_bStatic = 0;
}

CPicButton::~CPicButton()
{
    DeleteObject();
}

BEGIN_MESSAGE_MAP(CPicButton, CButton)
    //{{AFX_MSG_MAP(CPicButton)
    ON_WM_CTLCOLOR()
    ON_WM_ERASEBKGND()
    ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
    ON_WM_CAPTURECHANGED()
    ON_WM_KILLFOCUS()
    ON_WM_MOUSEMOVE()
    //}}AFX_MSG_MAP
    ON_MESSAGE(BM_SETCHECK, OnSetCheck)
    ON_MESSAGE(BM_GETCHECK, OnGetCheck)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPicButton message handlers

void CPicButton::DeleteObject()
{
    if(m_bmpNormal){
        ::DeleteObject(m_bmpNormal);
        m_bmpNormal=NULL;
    }
    if(m_bmpDisabled){
        ::DeleteObject(m_bmpDisabled);
        m_bmpDisabled=NULL;
    }
    if(m_bmpButton.GetSafeHandle()){
        m_bmpButton.DeleteObject();
    }
    if(m_bmpBack.GetSafeHandle()){
        m_bmpBack.DeleteObject();
    }
}
void CPicButton::SetBitmap(UINT nNormalID,UINT nDisableID)
{
    HINSTANCE   hInstResource=AfxFindResourceHandle(MAKEINTRESOURCE(nNormalID), RT_BITMAP);
    m_bmpNormal=(HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nNormalID), IMAGE_BITMAP, 0, 0, 0);
    if(nDisableID)
        m_bmpDisabled=(HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nDisableID), IMAGE_BITMAP, 0, 0, 0);
    else
        m_bmpDisabled=(HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nNormalID), IMAGE_BITMAP, 0, 0, 0);
}
void CPicButton::SetBitmap(LPCTSTR lpszNormal,LPCTSTR lpszDisabled)
{
    m_bmpNormal=(HBITMAP)::LoadImage(NULL, lpszNormal, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    if(lpszDisabled)
        m_bmpDisabled=(HBITMAP)::LoadImage(NULL, lpszDisabled, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    else
        m_bmpDisabled=NULL;
}
void CPicButton::SetBitmapEx(LPCTSTR lpszFile)
{
    if(lpszFile==NULL){
        m_bmpButton.DeleteObject();
    }
    else{
        if(!m_bmpButton.GetSafeHandle())m_bmpButton.DeleteObject();
        m_bmpButton.LoadBitmap(lpszFile);
    }
}
void CPicButton::SetBitmapEx(UINT nBitmapID)
{
    if(nBitmapID==0){
        m_bmpButton.DeleteObject();
    }
    else{
        if(!m_bmpButton.GetSafeHandle())m_bmpButton.DeleteObject();
        m_bmpButton.LoadBitmap(nBitmapID);
    }
}
void CPicButton::SetBackBmp(LPCTSTR lpszFile)
{
    if(lpszFile==NULL){
        m_bmpBack.DeleteObject();
    }
    else{
        if(!m_bmpBack.GetSafeHandle())m_bmpBack.DeleteObject();
        m_bmpBack.LoadBitmap(lpszFile);
    }
}
void CPicButton::SetBackBmp(UINT nNormalID)
{
    if(nNormalID==0){
        m_bmpBack.DeleteObject();
    }
    else{
        if(!m_bmpBack.GetSafeHandle())m_bmpBack.DeleteObject();
        m_bmpBack.LoadBitmap(nNormalID);
    }
}
void TransparentBlt2(HDC hdcDest,      // 目标DC
                     int nXOriginDest,   // 目标X偏移
                     int nYOriginDest,   // 目标Y偏移
                     int nWidthDest,     // 目标宽度
                     int nHeightDest,    // 目标高度
                     HDC hdcSrc,         // 源DC
                     int nXOriginSrc,    // 源X起点
                     int nYOriginSrc,    // 源Y起点
                     int nWidthSrc,      // 源宽度
                     int nHeightSrc,     // 源高度
                     UINT crTransparent  // 透明色,COLORREF类型
                     )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); // 创建兼容位图
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);          // 创建单色掩码位图
    HDC     hImageDC = CreateCompatibleDC(hdcDest);
    HDC     hMaskDC = CreateCompatibleDC(hdcDest);
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);

    // 将源DC中的位图拷贝到临时DC中
    if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
        BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
    else
        StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, 
        hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);

    // 设置透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明区域为白色,其它区域为黑色的掩码位图
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

    // 生成透明区域为黑色,其它区域保持不变的位图
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不变,其它部分变成黑色
    SetBkColor(hdcDest,RGB(0xff,0xff,0xff));
    SetTextColor(hdcDest,RGB(0,0,0));
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // "或"运算,生成最终效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);

    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP); 
}
void DrawTransparent(CDC *pDC,int x,int y,HBITMAP hBitmap)
{
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    CBitmap *pOldBitmap=memDC.SelectObject(CBitmap::FromHandle(hBitmap));
    BITMAP bm;
    ::GetObject(hBitmap,sizeof(BITMAP),&bm);
    COLORREF crTransparent=memDC.GetPixel(0,0);
    TransparentBlt2(pDC->m_hDC,x,y,bm.bmWidth,bm.bmHeight,memDC.m_hDC,0,0,bm.bmWidth,bm.bmHeight,crTransparent);
    if(pOldBitmap)memDC.SelectObject(pOldBitmap);
}
void DrawTransparent(CDC *pDC,int x,int y,HBITMAP hBitmap,int nIndex)
{
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    CBitmap *pOldBitmap=memDC.SelectObject(CBitmap::FromHandle(hBitmap));
    BITMAP bm;
    ::GetObject(hBitmap,sizeof(BITMAP),&bm);
    COLORREF crTransparent;
    int n = bm.bmHeight;
    if( n != 20 )
        crTransparent=memDC.GetPixel(0,0);
    else
        crTransparent=RGB(0,0,0);
    TransparentBlt2(pDC->m_hDC,x,y,bm.bmWidth/4-10,bm.bmHeight-5,memDC.m_hDC,nIndex*bm.bmWidth/4,0,bm.bmWidth/4,bm.bmHeight,crTransparent);
    if(pOldBitmap)memDC.SelectObject(pOldBitmap);
}

void CPicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{

    CRect rcItem=lpDrawItemStruct->rcItem;
    CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
    BOOL bFocus=lpDrawItemStruct->itemState&ODS_FOCUS;
    BOOL bSelected=lpDrawItemStruct->itemState&ODS_SELECTED;
    BOOL bDisabled=lpDrawItemStruct->itemState&ODS_DISABLED;
    CString strCaption;
    GetWindowText(strCaption);
    if(m_bCheckBox||m_bmpBack.GetSafeHandle()==NULL)
            pDC->FillSolidRect(&rcItem,m_BackColor);///////设置按钮背景色
    else if(m_bmpBack.GetSafeHandle())
        DrawTransparent(pDC,0,0,(HBITMAP)m_bmpBack,bDisabled?3:(bSelected?2:(bFocus?1:0)));
    if(m_bmpNormal)
    {
        BITMAP bm;
        ::GetObject(m_bmpNormal,sizeof(BITMAP),&bm);
        if(strCaption.IsEmpty())
        {
            DrawTransparent(pDC,
                (rcItem.Width()-bm.bmWidth)/2,
                (rcItem.Height()-bm.bmHeight)/2,
                bDisabled?m_bmpDisabled:m_bmpNormal);
        }
        else
        {
            if(m_nIconAlign==ALIGN_HORZ)
            {
                DrawTransparent(pDC,
                    2,
                    (rcItem.Height()-bm.bmHeight)/2,
                    bDisabled?m_bmpDisabled:m_bmpNormal);
                rcItem.left+=2+bm.bmWidth+2;
            }
            if(m_nIconAlign==ALIGN_VERT)
            {
                DrawTransparent(pDC,
                    (rcItem.Width()-bm.bmWidth)/2,
                    0,
                    bDisabled?m_bmpDisabled:m_bmpNormal);
                rcItem.top+=0+bm.bmHeight+0;
            }
        }
    }

    if(m_bmpButton.GetSafeHandle())
    {
        BITMAP bm;
        m_bmpButton.GetBitmap(&bm);
        bm.bmWidth/=4;
        if(strCaption.IsEmpty())
        {
            DrawTransparent(pDC,
                (rcItem.Width()-bm.bmWidth)/2,
                (rcItem.Height()-bm.bmHeight)/2,
                (HBITMAP)m_bmpButton,
                m_bCheckBox?(m_nCheck?0:1):(bDisabled?3:(bSelected?2:(bFocus?1:0)))
                );
        }
        else
        {
            if(m_nIconAlign==ALIGN_HORZ)
            {
                if(GetExStyle()&WS_EX_RIGHT)
                {
                    DrawTransparent(pDC,
                        rcItem.right-bm.bmWidth+3,
                        (rcItem.Height()-bm.bmHeight)/2,
                        (HBITMAP)m_bmpButton,
                        m_bCheckBox?(m_nCheck?0:1):(bDisabled?3:(bSelected?2:(bFocus?1:0)))
                        );
                    rcItem.right-=(2+bm.bmWidth+2);
                }
                else
                {
                    DrawTransparent(pDC,
                        2,
                        (rcItem.Height()-bm.bmHeight)/2,
                        (HBITMAP)m_bmpButton,
                        m_bCheckBox?(m_nCheck?0:1):(bDisabled?3:(bSelected?2:(bFocus?1:0)))
                        );
                    rcItem.left+=2+bm.bmWidth+2;
                }
            }
            if(m_nIconAlign==ALIGN_VERT)
            {
                DrawTransparent(pDC,
                    (rcItem.Width()-bm.bmWidth)/2+(bSelected?1:0),
                    0,
                    (HBITMAP)m_bmpButton,
                    m_bCheckBox?(m_nCheck?0:1):(bDisabled?3:(bSelected?2:(bFocus?1:0))));
                rcItem.top+=0+bm.bmHeight+0;
            }
        }
    }
    if(!strCaption.IsEmpty())
    {
        if(rcItem.left==0)rcItem.left=2;
        pDC->SetTextColor(m_TextColor);
        if(bDisabled)pDC->SetTextColor(RGB(192,192,192));
        if(!m_bCheckBox)
            if(bFocus)pDC->SetTextColor(m_FocusColor);//////设置按钮获得焦点时的颜色
        pDC->SetBkMode(TRANSPARENT);
        pDC->DrawText(strCaption,&rcItem,m_nTextAlign|DT_VCENTER|DT_SINGLELINE);
        pDC->SetBkMode(OPAQUE);
    }
}
void CPicButton::PreSubclassWindow() 
{
    if(GetButtonStyle()&BS_CHECKBOX)
        m_bCheckBox=1;
    ModifyStyle(0,BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}

HBRUSH CPicButton::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
    return (HBRUSH)::GetStockObject(NULL_BRUSH);
}

BOOL CPicButton::OnEraseBkgnd(CDC* pDC) 
{
    return TRUE;
}
LRESULT CPicButton::OnSetCheck(WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
        case BST_CHECKED:
        case BST_INDETERMINATE:
            SetCheck(1);
            break;
        default:
            SetCheck(0);
            break;
    }

    return 0;
}
LRESULT CPicButton::OnGetCheck(WPARAM wParam, LPARAM lParam)
{
    return GetCheck();
}
void CPicButton::SetCheck(int nCheck, BOOL bRepaint)
{
    if (nCheck == 0) 
        m_nCheck = 0;
    else 
        m_nCheck = 1;

    if (bRepaint) Invalidate();
}
int CPicButton::GetCheck()
{
    return m_nCheck;
}
BOOL CPicButton::OnClicked() 
{
    m_nCheck = !m_nCheck;
    if(m_bCheckBox)Invalidate();
    return FALSE;
}
void CPicButton::OnMouseMove(UINT nFlags, CPoint point)
{
    CWnd* pWnd;
    CWnd* pParent;

    CButton::OnMouseMove(nFlags, point);

    if (nFlags & MK_LBUTTON && m_MouseOnButton == FALSE) return;

    pWnd = GetActiveWindow();
    pParent = GetOwner();

    if ((GetCapture() != this) && (pWnd != NULL && pParent != NULL)) 
    {
        m_MouseOnButton = TRUE;
        SetFocus();
        SetCapture();
        Invalidate();
    }
    else
    {
        CRect rc;
        GetClientRect(&rc);
        if(!rc.PtInRect(point)){
            if(m_MouseOnButton == TRUE){
                m_MouseOnButton = FALSE;
                Invalidate();
            }
            if(!(nFlags & MK_LBUTTON)) ReleaseCapture();
        }
    }
}

void CPicButton::OnKillFocus(CWnd * pNewWnd)
{
    CButton::OnKillFocus(pNewWnd);

    if(m_MouseOnButton == TRUE){
        m_MouseOnButton = FALSE;
        Invalidate();
    }
}
void CPicButton::OnCaptureChanged(CWnd *pWnd) 
{
    if (m_MouseOnButton == TRUE){
        ReleaseCapture();
        Invalidate();
    }
    CButton::OnCaptureChanged(pWnd);
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值