因为按钮位于对话框右侧的透明区域,如果使用GDI绘制的话不能达到效果,因为GDI不支持alpha通道,绘制到透明的对话框上只能是透明的效果,而GDI+支持alpha通道,所以使用GDI+绘制就可以了。
首先看看自绘的按钮的类成员和重载函数:
class MyButton : public CButton
{
DECLARE_DYNAMIC(MyButton)
public:
MyButton();
virtual ~MyButton();
protected:
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
private :
BOOL m_tracking;
RECT rect;
bool m_hover;
virtual void PreSubclassWindow();
public:
Gdiplus::Image* normalImage;
Gdiplus::Image* hoverImage;
Gdiplus::Image* activeImage;
//WCHAR *image[3];
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
};
这个按钮实现了三种状态的变化:普通、悬停、按下,三种状态由三个png图片来显示。
具体实现如下:
// MyButton.cpp : 实现文件
//
#include "stdafx.h"
#include "MyButton.h"
// MyButton
IMPLEMENT_DYNAMIC(MyButton, CButton)
MyButton::MyButton():
activeImage(NULL),
normalImage(NULL),
hoverImage(NULL)
{
m_tracking = FALSE;
m_hover = false;
}
MyButton::~MyButton()
{
}
BEGIN_MESSAGE_MAP(MyButton, CButton)
ON_WM_MOUSEMOVE()
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_WM_ERASEBKGND()
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
using namespace Gdiplus;
void MyButton::DrawItem(LPDRAWITEMSTRUCT lpDS)
{
HBRUSH hbr = ::CreateSolidBrush(0);
::FillRect(lpDS->hDC,&lpDS->rcItem,hbr);
CDC memdc;
memdc.Attach(lpDS->hDC);
CDC bufferdc;
bufferdc.CreateCompatibleDC(&memdc);
CBitmap buffermap;
buffermap.CreateCompatibleBitmap(&memdc,lpDS->rcItem.right-lpDS->rcItem.left,lpDS->rcItem.bottom-lpDS->rcItem.top);
bufferdc.SelectObject(&buffermap);
//Graphics gs(lpDS->hDC);
Graphics gs(bufferdc.GetSafeHdc());
UINT W = activeImage->GetWidth(),H = activeImage->GetHeight();
if(lpDS->itemState&ODS_SELECTED)//按钮按下
{
gs.DrawImage(activeImage,0,0,W,H);
}
else if(m_hover)//鼠标移上
{
gs.DrawImage(hoverImage,0,0,W,H);
}
else//普通形态
{
gs.DrawImage(normalImage,0,0,W,H);
}
//gs.ReleaseHDC(lpDS->hDC);
gs.ReleaseHDC(bufferdc.GetSafeHdc());
memdc.BitBlt(0,0,lpDS->rcItem.right-lpDS->rcItem.left,lpDS->rcItem.bottom-lpDS->rcItem.top,&bufferdc,0,0,SRCCOPY);
memdc.Detach();
}
void MyButton::OnMouseMove(UINT nFlags, CPoint point)
{
if(!m_tracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER|TME_LEAVE;
tme.dwHoverTime =1;
tme.hwndTrack = m_hWnd;
m_tracking = _TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
}
LRESULT MyButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
if(m_hover == true)
{
m_hover = false;
m_tracking = FALSE;
Invalidate();
}
return 1;
}
LRESULT MyButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
if(m_hover == false)
{
m_hover = true;
m_tracking = FALSE;
Invalidate();
}
return 1;
}
void MyButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);
}
BOOL MyButton::OnEraseBkgnd(CDC* pDC)
{
return true;
}
BOOL MyButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCur = LoadCursor( NULL , IDC_HAND ) ;
::SetCursor(hCur);
return TRUE;
}
该类还是有很多不足之处,各位可以给点意见和建议,共同学习,共同进步。