第一种实现
#include "stdafx.h" #include "ToolBarButten.h" IMPLEMENT_DYNAMIC(CToolBarButten, CBitmapButton) CToolBarButten::CToolBarButten() { m_bOver/*(鼠标位于按钮之上)*/ = FALSE; m_bSelected/*(按钮被按下)*/ = FALSE; m_bTracking/*(在鼠标按下释放)*/ = FALSE; m_bFocus /*按钮为当前焦点*/ = FALSE; } CToolBarButten::~CToolBarButten() { } BEGIN_MESSAGE_MAP(CToolBarButten, CBitmapButton) ON_WM_MOUSEMOVE() ON_WM_MOUSELEAVE() ON_WM_MOUSEHOVER() END_MESSAGE_MAP() void CToolBarButten::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (!m_bTracking) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = m_hWnd; tme.dwFlags = TME_LEAVE | TME_HOVER; tme.dwHoverTime = 1;//光标停在按钮上,改变状态的时间,以1毫秒为单位 m_bTracking = _TrackMouseEvent(&tme); } CButton::OnMouseMove(nFlags, point); } void CToolBarButten::OnMouseLeave() { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_bOver = FALSE; // 鼠标没位于按钮之上 m_bTracking = FALSE; //鼠标离开按钮 InvalidateRect(NULL, FALSE); //让按钮重画 CButton::OnMouseLeave(); } void CToolBarButten::OnMouseHover(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_bOver = TRUE; //鼠标盘旋在按钮上空 InvalidateRect(NULL); //重画! CButton::OnMouseHover(nFlags, point); } void CToolBarButten::SetBitmapId(int nNormal,int nOver, int nPressed, int nFocus) { m_NormalBitmap.LoadBitmap(nNormal); m_PressedBitmap.LoadBitmap(nPressed); m_FocusBitmap.LoadBitmap(nFocus); m_OverBitmap.LoadBitmap(nOver); } void CToolBarButten::PreSubclassWindow() { // TODO: 在此添加专用代码和/或调用基类 CButton::PreSubclassWindow(); ModifyStyle(0, BS_OWNERDRAW); } void CToolBarButten::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CRect rect = lpDrawItemStruct->rcItem; CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); int nSaveDC = pDC->SaveDC(); UINT state = lpDrawItemStruct->itemState; //鼠标停留按钮的状态 if (m_bOver) { CDC MemDC; MemDC.CreateCompatibleDC(pDC); BITMAP bitmap; m_OverBitmap.GetBitmap(&bitmap); CBitmap *pbmpm_old = MemDC.SelectObject(&m_OverBitmap); pDC->SetStretchBltMode(COLORONCOLOR);//防止bmp图片失真 pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); } else { CDC MemDC; MemDC.CreateCompatibleDC(pDC); BITMAP bitmap; m_NormalBitmap.GetBitmap(&bitmap); CBitmap *pbmpm_old = MemDC.SelectObject(&m_NormalBitmap); pDC->SetStretchBltMode(COLORONCOLOR);//防止bmp图片失真 pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); } //按钮被按下(选中) if (state & ODS_SELECTED) { CDC MemDC; MemDC.CreateCompatibleDC(pDC); BITMAP bitmap; m_PressedBitmap.GetBitmap(&bitmap); CBitmap *pbmpm_old = MemDC.SelectObject(&m_PressedBitmap); pDC->SetStretchBltMode(COLORONCOLOR);//防止bmp图片失真 pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); } }
第二种实现
#include "stdafx.h" #include "ThreeStateBitmapButton.h" IMPLEMENT_DYNAMIC(CThreeStateBitmapButton, CBitmapButton) CThreeStateBitmapButton::CThreeStateBitmapButton() :m_bTracked(FALSE) { } BOOL CThreeStateBitmapButton::LoadListBitmap(UINT nIDBitmapResource, UINT nBitmapContainCount) { // delete old bitmaps (if present) m_bitmap.DeleteObject(); m_bitmapSel.DeleteObject(); m_bitmapFocus.DeleteObject(); m_bitmapDisabled.DeleteObject(); if (nBitmapContainCount < 1) { TRACE(traceAppMsg, 0, "Failed to load bitmap.\n"); return FALSE; } CBitmap bmpSrc; if (!bmpSrc.LoadBitmap(nIDBitmapResource)) { TRACE(traceAppMsg, 0, "Failed to load bitmap.\n"); return FALSE; // need this one image } BITMAP bmpInfo; bmpSrc.GetBitmap(&bmpInfo); CClientDC dc(this); CDC dcSrc, dcDest; dcSrc.CreateCompatibleDC(&dc); CBitmap *pOldBmpSrc = dcSrc.SelectObject(&bmpSrc); int nWidth = bmpInfo.bmWidth / nBitmapContainCount; int nHeight = bmpInfo.bmHeight; dcDest.CreateCompatibleDC(&dc); m_bitmap.CreateCompatibleBitmap(&dcSrc, nWidth, nHeight); CBitmap *pOldBmpDest = dcDest.SelectObject(&m_bitmap); dcDest.BitBlt(0, 0, nWidth, nHeight, &dcSrc, 0, 0, SRCCOPY); dcDest.SelectObject(pOldBmpDest); if (nBitmapContainCount > 1) { m_bitmapSel.CreateCompatibleBitmap(&dcSrc, nWidth, nHeight); pOldBmpDest = dcDest.SelectObject(&m_bitmapSel); dcDest.BitBlt(0, 0, nWidth, nHeight, &dcSrc, nWidth, 0, SRCCOPY); dcDest.SelectObject(pOldBmpDest); } if (nBitmapContainCount > 2) { m_bitmapFocus.CreateCompatibleBitmap(&dcSrc, nWidth, nHeight); pOldBmpDest = dcDest.SelectObject(&m_bitmapFocus); dcDest.BitBlt(0, 0, nWidth, nHeight, &dcSrc, nWidth * 2, 0, SRCCOPY); dcDest.SelectObject(pOldBmpDest); } if (nBitmapContainCount > 3) { m_bitmapDisabled.CreateCompatibleBitmap(&dcSrc, nWidth, nHeight); pOldBmpDest = dcDest.SelectObject(&m_bitmapDisabled); dcDest.BitBlt(0, 0, nWidth, nHeight, &dcSrc, nWidth * 3, 0, SRCCOPY); dcDest.SelectObject(pOldBmpDest); } dcSrc.SelectObject(pOldBmpSrc); return TRUE; } BEGIN_MESSAGE_MAP(CThreeStateBitmapButton, CBitmapButton) ON_WM_MOUSEMOVE() ON_WM_MOUSELEAVE() END_MESSAGE_MAP() void CThreeStateBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) { ASSERT(lpDIS != NULL); // must have at least the first bitmap loaded before calling DrawItem ASSERT(m_bitmap.m_hObject != NULL); // required // use the main bitmap for up, the selected bitmap for down CBitmap* pBitmap = &m_bitmap; UINT state = lpDIS->itemState; if ((state & ODS_SELECTED) && m_bitmapSel.m_hObject != NULL) pBitmap = &m_bitmapSel; //else if ((state & ODS_FOCUS) && m_bitmapFocus.m_hObject != NULL) //pBitmap = &m_bitmapFocus; // third image for focused else if ((state & ODS_DISABLED) && m_bitmapDisabled.m_hObject != NULL) pBitmap = &m_bitmapDisabled; // last image for disabled else if (m_bTracked && m_bitmapFocus.m_hObject != NULL) pBitmap = &m_bitmapFocus; // third image for focused // draw the whole button CDC* pDC = CDC::FromHandle(lpDIS->hDC); CDC memDC; memDC.CreateCompatibleDC(pDC); CBitmap* pOld = memDC.SelectObject(pBitmap); if (pOld == NULL) return; // destructors will clean up CRect rect; rect.CopyRect(&lpDIS->rcItem); pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); memDC.SelectObject(pOld); } void CThreeStateBitmapButton::OnMouseMove(UINT nFlags, CPoint point) { if (!m_bTracked) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 0; tme.hwndTrack = m_hWnd; TrackMouseEvent(&tme); m_bTracked = TRUE; Invalidate(FALSE); } CBitmapButton::OnMouseMove(nFlags, point); } void CThreeStateBitmapButton::OnMouseLeave() { m_bTracked = FALSE; Invalidate(FALSE); CBitmapButton::OnMouseLeave(); } void CThreeStateBitmapButton::PreSubclassWindow() { CBitmapButton::PreSubclassWindow(); ModifyStyle(0, BS_OWNERDRAW); }