VC++ 自绘位图按钮

本文介绍了一个在VC2010下用C++实现的自绘按钮类CBmpButton,该类不依赖窗口,直接在对话框上绘制BMP图片,支持不同状态的按钮图片设置,并处理鼠标消息。通过创建CBmpButton对象,设置图片资源并重写对话框的OnEraseBkgnd和鼠标事件来实现按钮的功能。
摘要由CSDN通过智能技术生成

 1.这里使用VC2010实现的按钮,采用自绘的方式

2.按钮的实现

没有使用任何的窗口,直接使用BMP图片画到对话框上(也可以窗口),这种方式,可以在SDK或MFC上都可以使用

CBmpButton类来管理BMP,绘画,鼠标消息等处理

 

头文件 “BmpButton.h”

 

#pragma once

#define WM_CMDMUSIC (WM_USER+1002)

class CBmpButton
{
public:
    CBmpButton(void);
    ~CBmpButton(void);

    BOOL Create(HWND hParent,UINT style, LPCRECT lpRect, WORD nID);
    void Draw(CDC* pDC);
    void DrawTransparent(BOOL bErase=FALSE);
    BOOL InKey(const CPoint& pt)const{return m_rect.PtInRect(pt);}
    BOOL InKey(int x,int y)const{return m_rect.PtInRect(CPoint(x,y));}

    BOOL Track(CPoint pt)const;
    void SetBitmap(UINT nUp,UINT nDown = 0, UINT nDisable = 0,UINT nHot = 0, COLORREF maskcolor=RGB(255,255,255));
    void SetBitmap(LPCTSTR lpszUp,LPCTSTR lpszDown = NULL, LPCTSTR lpszDisable = NULL, 
        LPCTSTR lpszHot = NULL,COLORREF maskcolor=RGB(255,255,255));/**/

    const CRect& GetRect()const{return m_rect;}
    CRect& GetRect(){return m_rect;}
    WORD GetID()const{return m_nID;}
    HWND GetParent()const {return m_hParent;}
    BOOL IsEnable()const{return m_bEnable;}

    void SetID(WORD nID){m_nID = nID;}
    void Enable(BOOL bEnable = TRUE){if(bEnable!=m_bEnable){m_bEnable = bEnable; Update();}}

    void Update(BOOL bReDraw = TRUE)const;
    void SetVisible(BOOL bVisible = TRUE);
    BOOL GetVisible()const{return m_style&WS_VISIBLE?TRUE:FALSE;}
    void    MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint=TRUE);
public:
    CBitmap  m_bmUp;
    CBitmap  m_bmDown;
    CBitmap  m_bmHot;
    CBitmap  m_bmDisable;
    //CBitmap  m_bmMask;
    COLORREF m_maskcolor;

    BOOL m_bEnable;
    BOOL m_bVisible;
    HWND m_hParent;            //父窗口句柄
    WORD m_nID;
protected:
    mutable BOOL m_bHot;
    mutable BOOL m_bPress;
    UINT    m_style;        //按钮分格
    CRect    m_rect;            //按钮在父窗口中的区域
    CDC            m_dcBk;            //背景
    CBitmap        m_bmpBk;        //空的背景图
    HBITMAP    m_pbmpOldBk;    
    BOOL    m_bDrawTransparent;    //透明
    SIZE    m_szButton;        //按钮图片的大小

    void PaintBk(CDC* pDC);
};


 

 

BmpButton.cpp源码-----------------------------------------------------------------------

#include "StdAfx.h"
#include ".\bmpbutton.h"

CBmpButton::CBmpButton(void)
{
    m_bHot = FALSE;
    m_bPress = FALSE;

    m_hParent = NULL;
    m_bEnable = TRUE;
    m_bVisible = TRUE;
    m_style        =0;
    m_rect.SetRect(0,0,0,0);
    m_nID = 0;

    m_bDrawTransparent = FALSE;
    m_pbmpOldBk = NULL;
}

CBmpButton::~CBmpButton(void)
{
    // Restore old bitmap (if any)
    if (m_dcBk.m_hDC && m_pbmpOldBk)
    {
        m_dcBk.SelectObject(m_pbmpOldBk);
        m_dcBk.DeleteDC();
        m_bmpBk.DeleteObject();
    } // if
}
BOOL CBmpButton::Create(HWND hParent,UINT style,LPCRECT lpRect,WORD nID)
{
    if(hParent==NULL) return FALSE;
    m_hParent = hParent;
    m_style    =style;
    if(m_style & WS_DISABLED)
        m_bEnable = FALSE;
    if(lpRect)m_rect = *lpRect;
    m_nID = nID;
    Update();
    return TRUE;

}
void CBmpButton::SetVisible(BOOL bVisible)
{
    if(bVisible)
        m_style&=WS_VISIBLE;
    else
        m_style&=~WS_VISIBLE;
}
void CBmpButton::SetBitmap(UINT nUp,UINT nDown, UINT nDisable,UINT nHot, COLORREF maskcolor)
{ 
    m_bmUp.DeleteObject();
    m_bmDown.DeleteObject();
    m_bmDisable.DeleteObject();
    m_bmHot.DeleteObject();
    m_maskcolor=maskcolor;

    if(nUp)
    {
        if(!m_bmUp.LoadBitmap(nUp))
        {
            OutputDebugString(_T("Warning : Load Up Bitmap Falid!\n"));
        }
        BITMAP bm;
        m_bmUp.GetBitmap(&bm);
        m_szButton.cx = bm.bmWidth; 
        m_szButton.cy = bm.bmHeight;
    }

    if(nDown)
    {
        if(!m_bmDown.LoadBitmap(nDown))
        {
            OutputDebugString(_T("Warning : Load Down Bitmap Falid!\n"));
        }
    }

    if(nDisable)
    {
        if(!m_bmDisable.LoadBitmap(nDisable))
        {
            OutputDebugString(_T("Warning : Load Disable Bitmap Falid!\n"));
        }
    }

    if(nHot)
    {
        if(!m_bmHot.LoadBitmap(nHot))
        {
            OutputDebugString(_T("Warning : Load Hot Bitmap Falid!\n"));
        }
    }
    Update();
}
void CBmpButton::SetBitmap(LPCTSTR lpszUp,LPCTSTR lpszDown, LPCTSTR lpszDisable,
                                LPCTSTR lpszHot,COLORREF maskcolor)
{
    m_bmUp.DeleteObject();
    m_bmDown.DeleteObject();
    m_bmDisable.DeleteObject();
    m_bmHot.DeleteObject();
    m_maskcolor=maskcolor;

    if(lpszUp!=NULL)
    {
        if(!m_bmUp.LoadBitmap(lpszUp))
        {
            OutputDebugString(_T("Warning : Load Up Bitmap Falid!\n"));
        }
    }

    if(lpszDown!=NULL)
    {
        if(!m_bmDown.LoadBitmap(lpszDown))
        {
            OutputDebugString(_T("Warning : Load Down Bitmap Falid!\n"));
        }
    }

    if(lpszDisable!=NULL)
    {
        if(!m_bmDisable.LoadBitmap(lpszDisable))
        {
            OutputDebugString(_T("Warning : Load Disable Bitmap Falid!\n"));
        }
    }

    if(lpszHot!=NULL)
    {
        if(!m_bmHot.LoadBitmap(lpszHot))
        {
            OutputDebugString(_T("Warning : Load Hot Bitmap Falid!\n"));
        }
    }
    Update();
}

void CBmpButton::Update(BOOL bReDraw)const
{
    if(m_hParent == NULL) return;

    InvalidateRect(m_hParent, &m_rect,TRUE);
    if(bReDraw) UpdateWindow(m_hParent);
}

void CBmpButton::Draw(CDC *pDC)
{
    if (m_style && WS_VISIBLE)
    {
        CRect rcClip;
        pDC->GetClipBox(&rcClip);
        if((rcClip & m_rect).IsRectEmpty())
            return;
        pDC->SetBkMode(TRANSPARENT);
        CDC memDC;
        memDC.CreateCompatibleDC(pDC);
        if (m_bDrawTransparent)
            PaintBk(pDC);

        if(m_bEnable){
            if(m_bPress && m_bHot){
                if(m_bmDown.m_hObject != NULL)
                    memDC.SelectObject(m_bmDown);
                else if(m_bmHot.m_hObject != NULL)
                    memDC.SelectObject(m_bmHot);
                else
                    memDC.SelectObject(m_bmUp);

            }
            else if(m_bHot)
            {

                if(m_bmHot.m_hObject != NULL)
                    memDC.SelectObject(m_bmHot);
                else
                    memDC.SelectObject(m_bmUp);

            }else
            {
                memDC.SelectObject(m_bmUp);
            }
        }else
        {
            if(m_bmDisable.m_hObject != NULL)
                memDC.SelectObject(m_bmDisable);
            else
                memDC.SelectObject(m_bmUp);
        }
        TransparentBlt(pDC->m_hDC,m_rect.left,m_rect.top, m_rect.Width(), m_rect.Height(),memDC.m_hDC,0,0,m_szButton.cx,m_szButton.cy,m_maskcolor);
    }
}

BOOL CBmpButton::Track(CPoint pt)const
{
    if(m_hParent == NULL) return FALSE;
    if(!InKey(pt)) return FALSE;

    // don't handle if capture already set
    if (::GetCapture() != NULL)
        return FALSE;

    // set capture to the window which received this message
    ::SetCapture(m_hParent);
    _ASSERT(m_hParent == ::GetCapture());

    m_bHot = TRUE;
    Update();
    if(m_bVisible && m_bEnable)
         ::SendMessage(m_hParent, WM_CMDMUSIC,(WPARAM)m_nID, 0);
    int px,py;
    // get messages until capture lost or cancelled/accepted
    for (;;)
    {
        MSG msg;
        _ASSERT(::GetMessage(&msg, NULL, 0, 0));

        if (::GetCapture() != m_hParent)
            break;

        switch (msg.message)
        {
        // handle movement/accept messages
        case WM_MOUSEMOVE:
        {
            px = (int)(short)LOWORD(msg.lParam);
            py = (int)(short)HIWORD(msg.lParam);

            BOOL bIn = InKey(px,py);
            if(m_bHot && !bIn || !m_bHot && bIn){
                m_bHot = bIn;
                
                Update();
            }
            if(!m_bPress){
                if(!bIn){
                    m_bHot = bIn;
                    Update();
                    goto ExitLoop;
                }
            }

            break;
        }
        case WM_LBUTTONDOWN:
            m_bPress = TRUE;
            Update();
            break;
        case WM_LBUTTONUP:
            px = (int)(short)LOWORD(msg.lParam);
            py = (int)(short)HIWORD(msg.lParam);

            m_bHot = FALSE;
            if(InKey(px,py) && m_bPress){
                m_bPress = FALSE;
                Update();
                ReleaseCapture();
                if(m_bVisible && m_bEnable)
                    ::SendMessage(m_hParent, WM_COMMAND,(WPARAM)m_nID, 0);
                goto ExitLoop;
            }
            m_bPress = FALSE;
            break;
        // just dispatch rest of the messages
        default:
            DispatchMessage(&msg);
            break;
        }
    }

ExitLoop:

    if(::GetCapture() == m_hParent)
        ::ReleaseCapture();

    return TRUE;
}
void CBmpButton::MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint)
{
    m_rect.left=x;m_rect.right=x+nWidth;
    m_rect.top=y;m_rect.bottom=y+nHeight;
}
void CBmpButton::DrawTransparent(BOOL bErase)
{
    m_bDrawTransparent = TRUE; 
    if (bErase) 
        ::InvalidateRect(m_hParent, m_rect, bErase); 
}
void CBmpButton::PaintBk(CDC* pDC)
{
    CRect rect1;

    rect1=m_rect;

    if (m_dcBk.m_hDC == NULL)
    {
        m_dcBk.CreateCompatibleDC(pDC);
        m_bmpBk.CreateCompatibleBitmap(pDC, rect1.Width(), rect1.Height());
        m_pbmpOldBk = (HBITMAP) m_dcBk.SelectObject(m_bmpBk);
        m_dcBk.BitBlt(0, 0, rect1.Width(), rect1.Height(), pDC,m_rect.left,m_rect.top, SRCCOPY);
    } 

    pDC->BitBlt(m_rect.left,m_rect.top, rect1.Width(), rect1.Height(), &m_dcBk, 0, 0, SRCCOPY);
} // End of PaintBk

 

 

//

3.这个类的使用方法

class CButtonDlg : public CDialogEx
{
public:
    CBmpButton m_button1;         //在主对话框中先定义对象
    CBmpButton m_button2;
public:
    CButtonDlg(CWnd* pParent = NULL);    // 标准构造函数

// 对话框数据
    enum { IDD = IDD_BUTTON_DIALOG };

   ...........

 

BOOL CButtonDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    //这里要定义好按钮的区域 rcButton

    CRect rcButton;
    rcButton.left = 20;    rcButton.right = rcButton.left + 64;
    rcButton.top = 50;    rcButton.bottom = rcButton.top + 64;

    //创建按钮实例
    if(m_button1.Create(m_hWnd,WS_VISIBLE,rcButton,200))
    {

        //设置按钮的图片
        m_button1.SetBitmap(IDB_NORMAL,IDB_DOWN,IDB_BITMAP4,IDB_HOT);
    }

    .............

}

 

那么接下来重要的部分, 因为这个类没有窗体,只能依赖其他窗口实现自己的绘画和鼠标事件

对话框要实现自绘画功能就要重载BOOL OnEraseBkgnd(CDC* pDC)事件

普通窗口的话,只要重载void OnPaint() 事件

我们这里是对话框为主体,那么绘画部分就如下处理

BOOL CButtonDlg::OnEraseBkgnd(CDC* pDC)
{
    BOOL bRet = CDialogEx::OnEraseBkgnd(pDC);
    m_button1.Draw(pDC);
    return bRet;
}

 

鼠标事件的实现如下:

void CButtonDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_button1.Track(point);

    CDialogEx::OnLButtonDown(nFlags, point);
}

void CButtonDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_button1.Track(point);

    CDialogEx::OnLButtonUp(nFlags, point);
}


void CButtonDlg::OnMouseMove(UINT nFlags, CPoint point)
{
    m_button1.Track(point);

    CDialogEx::OnMouseMove(nFlags, point);
}

 

请点击这里下载源码:      ==>    源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值