MFC自定义按钮实现CRgnButton

RgnButton.h

#pragma once
#include "afxwin.h"
class CRgnButton :
	public CButton
{
	DECLARE_DYNAMIC(CRgnButton)
public:
	CRgnButton();
	~CRgnButton();
	virtual void SetImage(Image* img);
	virtual void SetImageHover(Image* img);
	virtual void Create(CWnd* pParentWnd, UINT nID);
private:
	// 设置窗体区域
	void SetRgn(CRgn *region);
	// 读取图片的非透明区生成区域
	Region* CreateRegion(Image* img);
	Image* m_image;
	Point m_imgOffset;
	HRGN rgn, trgn;
	Image* m_imageHover;
	bool m_isHover;
	bool m_isHoverShowing;
protected:
	DECLARE_MESSAGE_MAP()
	virtual void PreSubclassWindow();
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

	afx_msg void OnMouseLeave();
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnMouseHover(UINT nFlags, CPoint point);
};


RgnButton.cpp

#include "stdafx.h"
#include "RgnButton.h"

IMPLEMENT_DYNAMIC(CRgnButton, CButton)
CRgnButton::CRgnButton()
{
	m_isHover = false;
	m_isHoverShowing = false;
	this->m_image = NULL;
	this->m_imageHover = NULL;
	this->m_imgOffset = Point(0, 0);
}
void CRgnButton::SetImage(Image* img)
{
	this->m_image = img;
	Region* rgn = CreateRegion(img);
	Graphics g(GetWindowDC()->m_hDC);
	HRGN hrgn = rgn->GetHRGN(&g);
	CRgn * crgn = CRgn::FromHandle(hrgn);
	SetRgn(crgn);
	delete rgn;
}
void CRgnButton::SetImageHover(Image* img)
{
	this->m_imageHover = img;
	/*
	Region* rgn = CreateRegion(img);
	Graphics g(GetWindowDC()->m_hDC);
	HRGN hrgn = rgn->GetHRGN(&g);
	CRgn * crgn = CRgn::FromHandle(hrgn);
	SetRgn(crgn);
	delete rgn;
	*/
}


CRgnButton::~CRgnButton()
{
	if (m_image)
	{
		delete m_image;
	}
}
void CRgnButton::Create(CWnd*pParentWnd, UINT nID){
	CWnd* target = pParentWnd->GetDlgItem(nID);
	CRect rc;
	target->GetWindowRect(&rc);
	pParentWnd->ScreenToClient(&rc);
	__super::Create(NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW, CRect(rc.left,
	rc.top,
	m_image->GetWidth() + rc.left,
	m_image->GetHeight() + rc.top),
	pParentWnd,
	nID);
}
Region* CRgnButton::CreateRegion(Image* img){
	Bitmap* bmp = new Bitmap(img->GetWidth(), img->GetHeight());
	Graphics* g = Graphics::FromImage(bmp);
	g->DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight());
	GraphicsPath gp;
	for (int i = 0; i < (int)bmp->GetWidth(); i++)
	{
		for (int j = 0; j < (int)bmp->GetHeight(); j++)
		{
			Color cl;
			bmp->GetPixel(i, j, &cl);
			if (cl.GetA() != 0)
			{
				gp.AddRectangle(Rect(i, j, 1, 1));
			}
		}
	}
	delete g;
	delete bmp;
	return new Region(&gp);
}

void CRgnButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	SetWindowRgn(rgn, true);
	if (m_isHover&&m_imageHover){
		m_isHoverShowing = true;
		Graphics g(lpDrawItemStruct->hDC);
		g.SetClip(trgn, CombineModeReplace);
		switch (lpDrawItemStruct->itemAction)
		{
		case ODA_SELECT:
		case ODA_DRAWENTIRE:
		case ODA_FOCUS:
		{
			g.DrawImage(m_imageHover, RectF((REAL)m_imgOffset.X, (REAL)m_imgOffset.Y, (REAL)m_image->GetWidth(), (REAL)m_image->GetHeight()));
		}
		break;
		}
	}
	else if (m_image)
	{
		Graphics g(lpDrawItemStruct->hDC);
		g.SetClip(trgn, CombineModeReplace);
		switch (lpDrawItemStruct->itemAction)
		{
			case ODA_SELECT:
			case ODA_DRAWENTIRE:
			case ODA_FOCUS:
				{
					g.DrawImage(m_image, RectF((REAL)m_imgOffset.X, (REAL)m_imgOffset.Y, (REAL)m_image->GetWidth(), (REAL)m_image->GetHeight()));
				}
				break;
		}
	}
}
BEGIN_MESSAGE_MAP(CRgnButton, CButton)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSELEAVE()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEHOVER()
END_MESSAGE_MAP()

void CRgnButton::SetRgn(CRgn *region){
	rgn = ::CreateRectRgn(0, 0, 0, 0);
	CombineRgn(rgn, region->operator HRGN(), NULL, RGN_COPY);
	trgn = ::CreateRectRgn(0, 0, 0, 0);
	CombineRgn(trgn, region->operator HRGN(), NULL, RGN_COPY);
}
void CRgnButton::PreSubclassWindow(){
	ModifyStyle(0, BS_OWNERDRAW | WS_CLIPSIBLINGS);
	CButton::PreSubclassWindow();
}

void CRgnButton::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_imgOffset.X = 1;
	m_imgOffset.Y = 1;
	CButton::OnLButtonDown(nFlags, point);
}


void CRgnButton::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_imgOffset.X = 0;
	m_imgOffset.Y = 0;
	CButton::OnLButtonUp(nFlags, point);
}


void CRgnButton::OnMouseLeave()
{
	m_isHover = false;
	m_imgOffset.X = 0;
	m_imgOffset.Y = 0;
	m_isHoverShowing = false;
	InvalidateRect(NULL, FALSE);
	CButton::OnMouseLeave();
}


void CRgnButton::OnMouseMove(UINT nFlags, CPoint point)
{
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(TRACKMOUSEEVENT);
	tme.dwFlags = TME_LEAVE | TME_HOVER;//要触发的消息
	tme.hwndTrack = this->m_hWnd;
	tme.dwHoverTime = 10;// 若不设此参数,则无法触发mouseHover
	::_TrackMouseEvent(&tme); //MOUSELEAVE|MOUSEHOVER消息由此函数触发
	CButton::OnMouseMove(nFlags, point);
}


void CRgnButton::OnMouseHover(UINT nFlags, CPoint point)
{
	m_isHover = true;
	m_imgOffset.X = 0;
	m_imgOffset.Y = 0;
	if (!m_isHoverShowing)InvalidateRect(NULL);
	CButton::OnMouseHover(nFlags, point);
}

你可能感兴趣的:(MFC自定义按钮实现CRgnButton)