【WTL】控件自绘之Button

一 :前言

按钮是最常见的一种控件,下面代码演示了WTL中Button的自绘


二:代码

.h头文件

class CXLPngButton : public CWindowImpl<CXLPngButton, CButton>, public COwnerDraw<CXLPngButton>
{
public:
	CXLPngButton(void);
	~CXLPngButton(void);

	BEGIN_MSG_MAP(CXLPngButton)
		MSG_WM_MOUSEMOVE(OnMouseMove)
		MSG_WM_MOUSELEAVE(OnMouseLeave)
		CHAIN_MSG_MAP_ALT(COwnerDraw<CXLPngButton>, 1)
	END_MSG_MAP()

public:
	void SetParentBg(CDC* pDC);
	void SetPng(UINT nResID, int nCount);
	void SetPng(CString strPng, int nCount);
	void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);

protected:
	void DrawMouseOut(CDC& dc, LPDRAWITEMSTRUCT lpDrawItemStruct);
	void DrawMouseOn(CDC& dc, LPDRAWITEMSTRUCT lpDrawItemStruct);
	void DrawMouseDown(CDC& dc, LPDRAWITEMSTRUCT lpDrawItemStruct);
	void DrawParentBg(CDC& dc, LPDRAWITEMSTRUCT lpDrawItemStruct);

	void OnMouseMove(UINT nFlags, CPoint point);
	void OnMouseLeave();

	int GetBtnState(LPDRAWITEMSTRUCT lpDS) const;

private:
	
	enum eMouseState
	{
		eState_MouseOut,
		eState_MouseOn,
		eState_MouseDown
	};

	CImage				m_ParentBgImg;
	CImage				m_PngImage;
	int					m_nWidth;
	int					m_nHeight;
	BOOL				m_bMouseOut;
};

.cpp 源文件

CXLPngButton::CXLPngButton(void) : m_nWidth(0),m_nHeight(0),m_bMouseOut(TRUE)
{
}

CXLPngButton::~CXLPngButton(void)
{
}

void CXLPngButton::SetPng(CString strPng, int nCount)
{
	if(!m_PngImage.IsNull())
	{
		m_PngImage.Destroy();
	}

	m_PngImage.Load(strPng);
	Utility::PreMultiply(m_PngImage);
	m_nWidth = m_PngImage.GetWidth()/nCount;
	m_nHeight = m_PngImage.GetHeight();

	ATLASSERT(!m_PngImage.IsNull());
	ATLASSERT(m_nWidth != 0);
	ATLASSERT(m_nHeight != 0);
}

void CXLPngButton::SetPng(UINT nResID, int nCount)
{
	if(!m_PngImage.IsNull())
	{
		m_PngImage.Destroy();
	}

	Utility::LoadImageFromResource(&m_PngImage, nResID, _T("PNG"));
	Utility::PreMultiply(m_PngImage);
	m_nWidth = m_PngImage.GetWidth()/nCount;
	m_nHeight = m_PngImage.GetHeight();

	ATLASSERT(!m_PngImage.IsNull());
	ATLASSERT(m_nWidth != 0);
	ATLASSERT(m_nHeight != 0);
}

void CXLPngButton::SetParentBg(CDC* pDC)
{
	if(!m_ParentBgImg.IsNull())
	{
		m_ParentBgImg.Destroy();
	}

	CRect rcClient;
	CRect rcParent;
	GetClientRect(&rcClient);
	GetWindowRect(&rcParent);
	GetParent().ScreenToClient(&rcParent);

	CDC	DCMemory;
	DCMemory.CreateCompatibleDC(pDC->m_hDC);

	CBitmap	BMPMemory;
	BMPMemory.CreateCompatibleBitmap(pDC->m_hDC, rcClient.Width(), rcClient.Height());
	
	HBITMAP hOldBitmap = DCMemory.SelectBitmap(BMPMemory);
	DCMemory.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), pDC->m_hDC, rcParent.left, rcParent.top, SRCCOPY);
	DCMemory.SelectBitmap(hOldBitmap);

	m_ParentBgImg.Attach((HBITMAP)BMPMemory.Detach());
}

void CXLPngButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	ATLASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
	ATLASSERT(lpDrawItemStruct->hDC != NULL);

	CDC dc = lpDrawItemStruct->hDC;
	int state = GetBtnState(lpDrawItemStruct);

	DrawParentBg(dc, lpDrawItemStruct);

	switch(state)
	{
	case eState_MouseOut:
		DrawMouseOut(dc, lpDrawItemStruct);
		break;
	case eState_MouseOn:
		DrawMouseOn(dc, lpDrawItemStruct);
		break;
	case eState_MouseDown:
		DrawMouseDown(dc, lpDrawItemStruct);
		break;
	default:
		ATLASSERT(FALSE);
		break;
	}
}

int CXLPngButton::GetBtnState(LPDRAWITEMSTRUCT lpDS) const
{
	CRect rcClient;
	GetClientRect(&rcClient);

	CPoint ptCursor;
	GetCursorPos(&ptCursor);
	ScreenToClient(&ptCursor);

	if(rcClient.PtInRect(ptCursor)) 
	{
		if(lpDS->itemState & ODS_SELECTED)
			return eState_MouseDown;
		else
			return eState_MouseOn;
	}
	else
	{
		return eState_MouseOut;
	}
}

void CXLPngButton::DrawMouseOut(CDC& dc, LPDRAWITEMSTRUCT lpDS)
{
	CRect rcSrc;
	rcSrc.SetRect(0, 0, m_nWidth, m_nHeight);

	m_PngImage.Draw(dc, CRect(lpDS->rcItem), rcSrc);
}

void CXLPngButton::DrawMouseDown(CDC& dc, LPDRAWITEMSTRUCT lpDS)
{
	CRect rcSrc;
	rcSrc.SetRect(2*m_nWidth, 0, 3*m_nWidth, m_nHeight);

	m_PngImage.Draw(dc, CRect(lpDS->rcItem), rcSrc);
}

void CXLPngButton::DrawMouseOn(CDC& dc, LPDRAWITEMSTRUCT lpDS)
{
	CRect rcSrc;
	rcSrc.SetRect(m_nWidth, 0, 2*m_nWidth, m_nHeight);

	m_PngImage.Draw(dc, CRect(lpDS->rcItem), rcSrc);
}

void CXLPngButton::OnMouseMove(UINT nFlags, CPoint point)
{
	if(m_bMouseOut)
	{
 		TRACKMOUSEEVENT track;
 		track.cbSize = sizeof(TRACKMOUSEEVENT);
 		track.dwFlags = TME_LEAVE;
 		track.dwHoverTime = 1000;
 		track.hwndTrack = m_hWnd;
 		TrackMouseEvent(&track);

		Invalidate();
		m_bMouseOut = FALSE;
	}

	DefWindowProc();
}

void CXLPngButton::OnMouseLeave()
{
	m_bMouseOut = TRUE;
	Invalidate();
}

void CXLPngButton::DrawParentBg(CDC& dc, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	if(!m_ParentBgImg.IsNull())
	{
		m_ParentBgImg.Draw(dc.m_hDC, CRect(lpDrawItemStruct->rcItem));
	}
}


你可能感兴趣的:(【WTL】控件自绘之Button)