下午无聊写的一个简单三态按钮,功能很有限,对于一般的不需要拉伸的对话框还比较适用(不能指定WS_CLIPCHILDREN风格):
class CBitmapButton : public CWindowImpl<CBitmapButton,CButton>, public COwnerDraw<CBitmapButton> { private: bool m_bTracking; bool m_bDCStored; CBitmap m_bitmapNor; CBitmap m_bitmapOver; CBitmap m_bitmapDown; public: CBitmapButton():m_bTracking(false),m_bDCStored(false) { } virtual ~CBitmapButton() { } void SetImage(CString strNormal, CString strHover, CString strDown) { m_bitmapNor=(HBITMAP)::LoadImage(NULL,strNormal,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); m_bitmapOver=(HBITMAP)::LoadImage(NULL,strHover,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); m_bitmapDown=(HBITMAP)::LoadImage(NULL,strDown,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); } void SetImage(UINT nNormalID, UINT nHoverID, UINT nDownID) { m_bitmapNor.LoadBitmap(nNormalID); m_bitmapOver.LoadBitmap(nHoverID); m_bitmapDown.LoadBitmap(nDownID); } BEGIN_MSG_MAP(CBitmapButton) MESSAGE_HANDLER(WM_CREATE,OnCreate) MESSAGE_HANDLER(WM_ERASEBKGND,OnEraseBkgnd) MESSAGE_HANDLER(WM_MOUSEMOVE,OnMouseMove) MESSAGE_HANDLER(WM_MOUSELEAVE,OnMouseLeave) CHAIN_MSG_MAP_ALT(COwnerDraw<CBitmapButton>,1) DEFAULT_REFLECTION_HANDLER() END_MSG_MAP() LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { Init(); bHandled = FALSE; return 1; } LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) { return 1; } LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { bHandled=FALSE; if (!m_bTracking) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof (tme); tme.hwndTrack = m_hWnd; tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 1; m_bTracking = _TrackMouseEvent(&tme); Invalidate(FALSE); } return 0; } LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { bHandled=false; m_bTracking = false; Invalidate(FALSE); return 0; } void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDCHandle dc = lpDrawItemStruct->hDC; CRect rcBtn( lpDrawItemStruct->rcItem); BITMAP bmpInfo; m_bitmapNor.GetBitmap(&bmpInfo); if (m_bTracking) { CDC dctemp; dctemp.CreateCompatibleDC(dc); dctemp.SelectBitmap(m_bitmapOver); ::TransparentBlt(dc,0,0, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom, dctemp.m_hDC, 0,0, bmpInfo.bmWidth, bmpInfo.bmHeight, RGB(255,0,255)); } if (lpDrawItemStruct->itemState & ODS_SELECTED) { CDC dctemp; dctemp.CreateCompatibleDC(dc); dctemp.SelectBitmap(m_bitmapDown); ::TransparentBlt(dc,0,0, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom, dctemp.m_hDC, 0,0, bmpInfo.bmWidth, bmpInfo.bmHeight, RGB(255,0,255)); } else if (!m_bTracking) { CDC dctemp; dctemp.CreateCompatibleDC(dc); dctemp.SelectBitmap(m_bitmapNor); ::TransparentBlt(dc,0,0, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom, dctemp.m_hDC, 0,0, bmpInfo.bmWidth, bmpInfo.bmHeight, RGB(255,0,255)); } int cchLen=GetWindowTextLength()+1; if (cchLen>1) { CFont oldFont=dc.SelectFont(GetFont()); LPTSTR strText=NULL; strText=new TCHAR[cchLen]; ::memset(strText,0,cchLen); GetWindowText(strText,cchLen); CRect rtText; GetClientRect(&rtText); dc.SetBkMode(TRANSPARENT); dc.DrawText(strText,cchLen-1,&rtText, DT_CENTER|DT_SINGLELINE |DT_VCENTER); delete strText; dc.SelectFont(oldFont); } } protected: void Init() { ModifyStyle(0,BS_OWNERDRAW); } };