下面的类不是我写的,我只简单介绍一下用法:
1>将AtlBitmapSkinButton.h头文件导入到工程中;
2>添加#include "AtlBitmapSkinButton.h"头文件;
3>添加按钮控件IDC_BUTTON1,并将其Ower Draw属性改为True;
4>在
BEGIN_MSG_MAP(CDialog)
......
REFLECT_NOTIFICATIONS()//这句不要忘了!
END_MSG_MAP()
5>CAtlBitmapButton m_button1;
6>在OnInitDialog里面添加如下代码:
m_button1.SubclassWindow(GetDlgItem(IDC_BUTTON1));
m_button1.LoadStateBitmaps(IDB_BITMAP1, IDB_BITMAP2, IDB_BITMAP3);
IDB_BITMAP1:当前显示,IDB_BITMAP2:鼠标按下,IDB_BITMAP3:鼠标滑过
class CAtlBitmapButton; typedef CWindowImpl < CAtlBitmapButton, CWindow, CWinTraits < WS_CHILD | WS_VISIBLE | BS_OWNERDRAW> > CCustButton; class CAtlBitmapButton : public CCustButton { public: DECLARE_WND_SUPERCLASS(NULL, _T("BUTTON")) CAtlBitmapButton() { m_bButtonDown = m_bTracking = false; } ~CAtlBitmapButton() { } BEGIN_MSG_MAP(CAtlBitmapButton) MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP) MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) END_MSG_MAP() LRESULT OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLASSERT(m_bTracking); m_bTracking = false; Invalidate(); return 0; } LRESULT OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; HDC hdcMem = ::CreateCompatibleDC(lpdis->hDC); HBITMAP hbmMem = ::CreateCompatibleBitmap(lpdis->hDC, lpdis->rcItem.right - lpdis->rcItem.left, lpdis->rcItem.bottom - lpdis->rcItem.top); HGDIOBJ hbmOld = ::SelectObject(hdcMem, (HGDIOBJ)hbmMem); HBRUSH transparent = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); RECT rect={lpdis->rcItem.left, lpdis->rcItem.top, lpdis->rcItem .right, lpdis->rcItem.bottom }; int cx = rect.right - rect.left; int cy = rect.bottom -rect.top; FillRect(hdcMem , &rect, transparent); POINT mouse_position; if ((m_bButtonDown) &&(::GetCapture() == m_hWnd) &&(::GetCursorPos(&mouse_position))) { if (::WindowFromPoint(mouse_position) == m_hWnd) { if ((GetState() & BST_PUSHED) != BST_PUSHED) { SetState(TRUE); return -1; } } else { if ((GetState() & BST_PUSHED) == BST_PUSHED) { SetState(FALSE); return -1; } } } if (lpdis->itemState & ODS_SELECTED) { if (!m_bmpDown) { FillRect(lpdis->hDC, &rect, CreateSolidBrush(GetSysColor(COLOR_BTNFACE))); } else DrawBitmap(lpdis->hDC, m_bmpDown, rect); } else { if (!m_bmpNormal) FillRect(lpdis->hDC, &rect, CreateSolidBrush(GetSysColor(COLOR_BTNFACE))); else { if ((m_bTracking) && m_bmpOver) DrawBitmap(lpdis->hDC, m_bmpOver, rect); else DrawBitmap(lpdis->hDC, m_bmpNormal, rect); } } ::SelectObject(hdcMem, hbmOld); ::DeleteObject((HGDIOBJ)hbmMem); ::DeleteDC(hdcMem); return 0; } public: LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. return 0; } LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 1; } LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. if (m_bTracking) { TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_CANCEL | TME_LEAVE, m_hWnd, 0 }; if (::_TrackMouseEvent(&t)) { m_bTracking = false; } } m_bButtonDown = true; bHandled = false; return 0; } LRESULT OnLButtonUP(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. m_bButtonDown = false; bHandled = false; return 0; } LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. if ((m_bButtonDown) &&(::GetCapture() == m_hWnd)) { POINT p2; p2.x = LOWORD(lParam); p2.y = HIWORD(lParam); ::ClientToScreen(m_hWnd, &p2); HWND mouse_wnd = ::WindowFromPoint(p2); bool pressed = ((GetState() & BST_PUSHED) == BST_PUSHED); bool need_pressed = (mouse_wnd == m_hWnd); if (pressed != need_pressed) { SetState(need_pressed ? TRUE : FALSE); Invalidate(); } } else { if (!m_bTracking) { TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0 }; if (::_TrackMouseEvent(&t)) { m_bTracking = true; Invalidate(); } } } bHandled = false; return 0; } int GetBitmapWidth(HBITMAP hBitmap) { BITMAP bm; GetObject(hBitmap, sizeof(BITMAP), (PSTR)&bm); return bm.bmWidth; } int GetBitmapHeight(HBITMAP hBitmap) { BITMAP bm; GetObject(hBitmap, sizeof(BITMAP), (PSTR)&bm); return bm.bmHeight; } void DrawBitmap(HDC hdc, HBITMAP hBitmap, RECT& rc) { if (!hBitmap) { ATLTRACE("/nUnable to load bitmap...."); return; } int cx = rc.right - rc.left; int cy = rc.bottom - rc.top; int nbmpWidth= GetBitmapWidth(hBitmap); int nbmpHeight = GetBitmapHeight(hBitmap); HDC hdcMem = CreateCompatibleDC(hdc); SelectObject(hdcMem, hBitmap); StretchBlt(hdc, rc.left, rc.top, cx, cy, hdcMem, 0, 0, nbmpWidth, nbmpHeight, SRCCOPY); DeleteDC(hdcMem); } void LoadStateBitmaps(UINT nSelected, UINT nDown, UINT nOver) { if (m_bmpNormal) m_bmpNormal.DeleteObject(); if (m_bmpDown) m_bmpDown.DeleteObject(); if (m_bmpOver) m_bmpOver.DeleteObject(); m_bmpNormal.LoadBitmap(nSelected); m_bmpDown.LoadBitmap(nDown); m_bmpOver.LoadBitmap(nOver); } UINT GetState() const { ATLASSERT(::IsWindow(m_hWnd)); return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L); } void SetState(BOOL bHighlight) { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L); } private: int m_nBorder; CBitmap m_bmpNormal, m_bmpDown, m_bmpOver; short m_DrawMode; BOOL m_bTracking; BOOL m_bButtonDown; LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // TODO : Add Code for message handler. Call DefWindowProc if necessary. if (::GetCapture() == m_hWnd) { ::ReleaseCapture(); ATLASSERT(!m_bTracking); m_bButtonDown = false; ATLTRACE("/nKillFocus"); } bHandled = false; return 0; } };
from: http://www.codeproject.com/KB/wtl/mousetrack.aspx