下面的类不是我写的,我只简单介绍一下用法:
- 将AtlBitmapSkinButton.h头文件导入到工程中;
- 添加#include “AtlBitmapSkinButton.h”头文件;
- 添加按钮控件IDC_BUTTON1,并将其Ower Draw属性改为True;
- 在
BEGIN_MSG_MAP(CDialog)
......
REFLECT_NOTIFICATIONS()//这句不要忘了!
END_MSG_MAP()
- CAtlBitmapButton m_button1;
- 在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;
}
};
(迁移2011-05-09)