一 :前言
按钮是最常见的一种控件,下面代码演示了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)); } }