MFC + CxImage 实现自绘半透明按钮

环境:VS2008 + CxImage

btn.h

#pragma once


// CBtn
#include "ximage/ximage.h"

class CBtn : public CButton
{
	DECLARE_DYNAMIC(CBtn)
private:
	CxImage * m_pImgNormal;
	CxImage * m_pImgOver;
	CxImage * m_pImgDown;
	CxImage * m_pImgFocus;
	CxImage * m_pImgDisable;

	BOOL m_bTracking;
	BOOL m_bMouseOver;
	BOOL m_bLBtnDown;
public:
	CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled=0,UINT imgID_Focus=0);
	virtual ~CBtn();

protected:
	DECLARE_MESSAGE_MAP()
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	afx_msg void OnDestroy();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnMouseLeave();
	afx_msg void OnMouseHover(UINT nFlags, CPoint point);
protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
public:
	void PaintParent();
	virtual BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnBnDoubleclicked();
	afx_msg void OnKillFocus(CWnd* pNewWnd);
};

btn.cpp

// Btn.cpp : 实现文件
//

#include "stdafx.h"
#include "Btn.h"


// CBtn

IMPLEMENT_DYNAMIC(CBtn, CButton)

CBtn::CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled,UINT imgID_Focus):
	  m_pImgNormal(NULL)
	, m_pImgOver(NULL)
	, m_pImgDown(NULL)
	, m_pImgFocus(NULL)
	, m_pImgDisable(NULL)
	, m_bTracking(FALSE)
	, m_bMouseOver(FALSE)
	, m_bLBtnDown(FALSE)
{
	if(imgID_Normal > 0)
	{
		if(!m_pImgNormal)
			m_pImgNormal = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgNormal ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Normal),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if(imgID_Focus > 0)
	{
		if(!m_pImgFocus)
			m_pImgFocus = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgFocus ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Focus),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_LbtnDown>0 )
	{
		if(!m_pImgDown)
			m_pImgDown = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgDown ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_LbtnDown),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_Disabled > 0 )
	{
		if(!m_pImgDisable)
			m_pImgDisable = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgDisable ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Disabled),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_Over > 0)
	{
		if(!m_pImgOver)
			m_pImgOver = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgOver ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Over),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
}

CBtn::~CBtn()
{
}

BEGIN_MESSAGE_MAP(CBtn, CWnd)
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSELEAVE()
	ON_WM_MOUSEHOVER()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_CONTROL_REFLECT(BN_DOUBLECLICKED, &CBtn::OnBnDoubleclicked)
	ON_WM_KILLFOCUS()
END_MESSAGE_MAP()


// CBtn 消息处理程序
void CBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC ButtonDC; 
	CRect rc;
    
    ButtonDC.Attach(lpDrawItemStruct->hDC); //得到用于绘制按钮的DC 
	rc=lpDrawItemStruct->rcItem; //获取按钮所占的矩形大小

	UINT state = lpDrawItemStruct->itemState; //获取按钮目前所处的状态,根据不同的状态绘制不同的按钮 

	if(state&ODS_DISABLED && m_pImgDisable) 
    { 
		m_pImgDisable ->Draw(ButtonDC.GetSafeHdc(),rc);
	}
	else
	{

		if( m_bLBtnDown && m_pImgDown)
		{
			m_pImgDown ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(m_bMouseOver && m_pImgOver)
		{
			m_pImgOver ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(state&ODS_FOCUS && m_pImgFocus) 
		{ 
			m_pImgFocus ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(m_pImgNormal)
		{
			m_pImgNormal ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
	}
}

void CBtn::OnDestroy()
{
	CButton::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	if(m_pImgNormal)
	{
		m_pImgNormal ->Destroy();
		delete m_pImgNormal;
		m_pImgNormal = NULL;
	}
	if(m_pImgOver)
	{
		m_pImgOver ->Destroy();
		delete m_pImgOver;
		m_pImgOver = NULL;
	}
	if(m_pImgDown)
	{
		m_pImgDown ->Destroy();
		delete m_pImgDown;
		m_pImgDown = NULL;
	}
	if(m_pImgFocus)
	{
		m_pImgFocus ->Destroy();
		delete m_pImgFocus;
		m_pImgFocus = NULL;
	}
	if(m_pImgDisable)
	{
		m_pImgDisable ->Destroy();
		delete m_pImgDisable;
		m_pImgDisable = NULL;
	}
}

BOOL CBtn::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return TRUE;
	//return CButton::OnEraseBkgnd(pDC);
}

BOOL CBtn::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此添加专用代码和/或调用基类
	cs.style |= BS_OWNERDRAW;

	return CButton::PreCreateWindow(cs);
}

void CBtn::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bMouseOver = TRUE;
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT   tme; 
		tme.cbSize		=   sizeof(TRACKMOUSEEVENT); 
		tme.dwFlags		=   TME_LEAVE|TME_HOVER; //
		tme.hwndTrack   =   GetSafeHwnd(); 
		tme.dwHoverTime	=   8; 
		_TrackMouseEvent(&tme);
		m_bTracking = TRUE;
	}
	CButton::OnMouseMove(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnMouseLeave()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bMouseOver	=   FALSE; 
	m_bTracking		=   FALSE;  
	m_bLBtnDown		=	FALSE;
	PaintParent();
	CButton::OnMouseLeave();
}

void CBtn::OnMouseHover(UINT nFlags, CPoint point)
{
	m_bMouseOver = TRUE;
	PaintParent();
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::PaintParent()
{
	CRect   rect; 
	GetWindowRect(&rect); 
	GetParent()-> ScreenToClient(&rect); 
	GetParent()-> InvalidateRect(&rect);
}

BOOL CBtn::Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
	BOOL OK=CButton::Create(lpszCaption, dwStyle, rect, pParentWnd, nID);
	ModifyStyleEx(0, WS_EX_TRANSPARENT);// WS_EX_LAYERED||WS_EX_TRANSPARENT  
	return OK;
}

void CBtn::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLBtnDown = TRUE;
	PaintParent();
	CButton::OnLButtonDown(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_bLBtnDown = FALSE;
	PaintParent();
	CButton::OnLButtonUp(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnBnDoubleclicked()
{
	// TODO: 在此添加控件通知处理程序代码
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

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

	// TODO: 在此处添加消息处理程序代码
	PaintParent();
}

调用

///头文件中添加
...
#include "Btn.h"
...
        enum {emTestBtnId1=8099,emTestBtnId2,emTestBtnId3};
	CBtn m_btnTest1,m_btnTest2,m_btnTest3;//test

///在构造函数初始化列表中初始化变量(IDB_PNG_BTN_TEST_*为Png图片资源ID)   
    , m_btnTest1(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE,
            IDB_PNG_BTN_TEST_FOCUS) 
    , m_btnTest2(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/) 
    , m_btnTest3(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/)

在OnInitDialog()函数中创建按钮
    //test 
    m_btnTest1.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,10,58,58),this,emTestBtnId1); 
    m_btnTest2.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,60,58,108),this,emTestBtnId2); 
    m_btnTest3.Create(_T("test"),WS_VISIBLE | WS_CHILD |WS_DISABLED,CRect(10,110,58,158),this,emTestBtnId2);


效果图



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值