1.这里使用VC2010实现的按钮,采用自绘的方式
2.按钮的实现
没有使用任何的窗口,直接使用BMP图片画到对话框上(也可以窗口),这种方式,可以在SDK或MFC上都可以使用
CBmpButton类来管理BMP,绘画,鼠标消息等处理
头文件 “BmpButton.h”
#pragma once
#define WM_CMDMUSIC (WM_USER+1002)
class CBmpButton
{
public:
CBmpButton(void);
~CBmpButton(void);
BOOL Create(HWND hParent,UINT style, LPCRECT lpRect, WORD nID);
void Draw(CDC* pDC);
void DrawTransparent(BOOL bErase=FALSE);
BOOL InKey(const CPoint& pt)const{return m_rect.PtInRect(pt);}
BOOL InKey(int x,int y)const{return m_rect.PtInRect(CPoint(x,y));}
BOOL Track(CPoint pt)const;
void SetBitmap(UINT nUp,UINT nDown = 0, UINT nDisable = 0,UINT nHot = 0, COLORREF maskcolor=RGB(255,255,255));
void SetBitmap(LPCTSTR lpszUp,LPCTSTR lpszDown = NULL, LPCTSTR lpszDisable = NULL,
LPCTSTR lpszHot = NULL,COLORREF maskcolor=RGB(255,255,255));/**/
const CRect& GetRect()const{return m_rect;}
CRect& GetRect(){return m_rect;}
WORD GetID()const{return m_nID;}
HWND GetParent()const {return m_hParent;}
BOOL IsEnable()const{return m_bEnable;}
void SetID(WORD nID){m_nID = nID;}
void Enable(BOOL bEnable = TRUE){if(bEnable!=m_bEnable){m_bEnable = bEnable; Update();}}
void Update(BOOL bReDraw = TRUE)const;
void SetVisible(BOOL bVisible = TRUE);
BOOL GetVisible()const{return m_style&WS_VISIBLE?TRUE:FALSE;}
void MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint=TRUE);
public:
CBitmap m_bmUp;
CBitmap m_bmDown;
CBitmap m_bmHot;
CBitmap m_bmDisable;
//CBitmap m_bmMask;
COLORREF m_maskcolor;
BOOL m_bEnable;
BOOL m_bVisible;
HWND m_hParent; //父窗口句柄
WORD m_nID;
protected:
mutable BOOL m_bHot;
mutable BOOL m_bPress;
UINT m_style; //按钮分格
CRect m_rect; //按钮在父窗口中的区域
CDC m_dcBk; //背景
CBitmap m_bmpBk; //空的背景图
HBITMAP m_pbmpOldBk;
BOOL m_bDrawTransparent; //透明
SIZE m_szButton; //按钮图片的大小
void PaintBk(CDC* pDC);
};
BmpButton.cpp源码-----------------------------------------------------------------------
#include "StdAfx.h"
#include ".\bmpbutton.h"
CBmpButton::CBmpButton(void)
{
m_bHot = FALSE;
m_bPress = FALSE;
m_hParent = NULL;
m_bEnable = TRUE;
m_bVisible = TRUE;
m_style =0;
m_rect.SetRect(0,0,0,0);
m_nID = 0;
m_bDrawTransparent = FALSE;
m_pbmpOldBk = NULL;
}
CBmpButton::~CBmpButton(void)
{
// Restore old bitmap (if any)
if (m_dcBk.m_hDC && m_pbmpOldBk)
{
m_dcBk.SelectObject(m_pbmpOldBk);
m_dcBk.DeleteDC();
m_bmpBk.DeleteObject();
} // if
}
BOOL CBmpButton::Create(HWND hParent,UINT style,LPCRECT lpRect,WORD nID)
{
if(hParent==NULL) return FALSE;
m_hParent = hParent;
m_style =style;
if(m_style & WS_DISABLED)
m_bEnable = FALSE;
if(lpRect)m_rect = *lpRect;
m_nID = nID;
Update();
return TRUE;
}
void CBmpButton::SetVisible(BOOL bVisible)
{
if(bVisible)
m_style&=WS_VISIBLE;
else
m_style&=~WS_VISIBLE;
}
void CBmpButton::SetBitmap(UINT nUp,UINT nDown, UINT nDisable,UINT nHot, COLORREF maskcolor)
{
m_bmUp.DeleteObject();
m_bmDown.DeleteObject();
m_bmDisable.DeleteObject();
m_bmHot.DeleteObject();
m_maskcolor=maskcolor;
if(nUp)
{
if(!m_bmUp.LoadBitmap(nUp))
{
OutputDebugString(_T("Warning : Load Up Bitmap Falid!\n"));
}
BITMAP bm;
m_bmUp.GetBitmap(&bm);
m_szButton.cx = bm.bmWidth;
m_szButton.cy = bm.bmHeight;
}
if(nDown)
{
if(!m_bmDown.LoadBitmap(nDown))
{
OutputDebugString(_T("Warning : Load Down Bitmap Falid!\n"));
}
}
if(nDisable)
{
if(!m_bmDisable.LoadBitmap(nDisable))
{
OutputDebugString(_T("Warning : Load Disable Bitmap Falid!\n"));
}
}
if(nHot)
{
if(!m_bmHot.LoadBitmap(nHot))
{
OutputDebugString(_T("Warning : Load Hot Bitmap Falid!\n"));
}
}
Update();
}
void CBmpButton::SetBitmap(LPCTSTR lpszUp,LPCTSTR lpszDown, LPCTSTR lpszDisable,
LPCTSTR lpszHot,COLORREF maskcolor)
{
m_bmUp.DeleteObject();
m_bmDown.DeleteObject();
m_bmDisable.DeleteObject();
m_bmHot.DeleteObject();
m_maskcolor=maskcolor;
if(lpszUp!=NULL)
{
if(!m_bmUp.LoadBitmap(lpszUp))
{
OutputDebugString(_T("Warning : Load Up Bitmap Falid!\n"));
}
}
if(lpszDown!=NULL)
{
if(!m_bmDown.LoadBitmap(lpszDown))
{
OutputDebugString(_T("Warning : Load Down Bitmap Falid!\n"));
}
}
if(lpszDisable!=NULL)
{
if(!m_bmDisable.LoadBitmap(lpszDisable))
{
OutputDebugString(_T("Warning : Load Disable Bitmap Falid!\n"));
}
}
if(lpszHot!=NULL)
{
if(!m_bmHot.LoadBitmap(lpszHot))
{
OutputDebugString(_T("Warning : Load Hot Bitmap Falid!\n"));
}
}
Update();
}
void CBmpButton::Update(BOOL bReDraw)const
{
if(m_hParent == NULL) return;
InvalidateRect(m_hParent, &m_rect,TRUE);
if(bReDraw) UpdateWindow(m_hParent);
}
void CBmpButton::Draw(CDC *pDC)
{
if (m_style && WS_VISIBLE)
{
CRect rcClip;
pDC->GetClipBox(&rcClip);
if((rcClip & m_rect).IsRectEmpty())
return;
pDC->SetBkMode(TRANSPARENT);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
if (m_bDrawTransparent)
PaintBk(pDC);
if(m_bEnable){
if(m_bPress && m_bHot){
if(m_bmDown.m_hObject != NULL)
memDC.SelectObject(m_bmDown);
else if(m_bmHot.m_hObject != NULL)
memDC.SelectObject(m_bmHot);
else
memDC.SelectObject(m_bmUp);
}
else if(m_bHot)
{
if(m_bmHot.m_hObject != NULL)
memDC.SelectObject(m_bmHot);
else
memDC.SelectObject(m_bmUp);
}else
{
memDC.SelectObject(m_bmUp);
}
}else
{
if(m_bmDisable.m_hObject != NULL)
memDC.SelectObject(m_bmDisable);
else
memDC.SelectObject(m_bmUp);
}
TransparentBlt(pDC->m_hDC,m_rect.left,m_rect.top, m_rect.Width(), m_rect.Height(),memDC.m_hDC,0,0,m_szButton.cx,m_szButton.cy,m_maskcolor);
}
}
BOOL CBmpButton::Track(CPoint pt)const
{
if(m_hParent == NULL) return FALSE;
if(!InKey(pt)) return FALSE;
// don't handle if capture already set
if (::GetCapture() != NULL)
return FALSE;
// set capture to the window which received this message
::SetCapture(m_hParent);
_ASSERT(m_hParent == ::GetCapture());
m_bHot = TRUE;
Update();
if(m_bVisible && m_bEnable)
::SendMessage(m_hParent, WM_CMDMUSIC,(WPARAM)m_nID, 0);
int px,py;
// get messages until capture lost or cancelled/accepted
for (;;)
{
MSG msg;
_ASSERT(::GetMessage(&msg, NULL, 0, 0));
if (::GetCapture() != m_hParent)
break;
switch (msg.message)
{
// handle movement/accept messages
case WM_MOUSEMOVE:
{
px = (int)(short)LOWORD(msg.lParam);
py = (int)(short)HIWORD(msg.lParam);
BOOL bIn = InKey(px,py);
if(m_bHot && !bIn || !m_bHot && bIn){
m_bHot = bIn;
Update();
}
if(!m_bPress){
if(!bIn){
m_bHot = bIn;
Update();
goto ExitLoop;
}
}
break;
}
case WM_LBUTTONDOWN:
m_bPress = TRUE;
Update();
break;
case WM_LBUTTONUP:
px = (int)(short)LOWORD(msg.lParam);
py = (int)(short)HIWORD(msg.lParam);
m_bHot = FALSE;
if(InKey(px,py) && m_bPress){
m_bPress = FALSE;
Update();
ReleaseCapture();
if(m_bVisible && m_bEnable)
::SendMessage(m_hParent, WM_COMMAND,(WPARAM)m_nID, 0);
goto ExitLoop;
}
m_bPress = FALSE;
break;
// just dispatch rest of the messages
default:
DispatchMessage(&msg);
break;
}
}
ExitLoop:
if(::GetCapture() == m_hParent)
::ReleaseCapture();
return TRUE;
}
void CBmpButton::MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint)
{
m_rect.left=x;m_rect.right=x+nWidth;
m_rect.top=y;m_rect.bottom=y+nHeight;
}
void CBmpButton::DrawTransparent(BOOL bErase)
{
m_bDrawTransparent = TRUE;
if (bErase)
::InvalidateRect(m_hParent, m_rect, bErase);
}
void CBmpButton::PaintBk(CDC* pDC)
{
CRect rect1;
rect1=m_rect;
if (m_dcBk.m_hDC == NULL)
{
m_dcBk.CreateCompatibleDC(pDC);
m_bmpBk.CreateCompatibleBitmap(pDC, rect1.Width(), rect1.Height());
m_pbmpOldBk = (HBITMAP) m_dcBk.SelectObject(m_bmpBk);
m_dcBk.BitBlt(0, 0, rect1.Width(), rect1.Height(), pDC,m_rect.left,m_rect.top, SRCCOPY);
}
pDC->BitBlt(m_rect.left,m_rect.top, rect1.Width(), rect1.Height(), &m_dcBk, 0, 0, SRCCOPY);
} // End of PaintBk
//
3.这个类的使用方法
class CButtonDlg : public CDialogEx
{
public:
CBmpButton m_button1; //在主对话框中先定义对象
CBmpButton m_button2;
public:
CButtonDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_BUTTON_DIALOG };
...........
}
BOOL CButtonDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
//这里要定义好按钮的区域 rcButton
CRect rcButton;
rcButton.left = 20; rcButton.right = rcButton.left + 64;
rcButton.top = 50; rcButton.bottom = rcButton.top + 64;
//创建按钮实例
if(m_button1.Create(m_hWnd,WS_VISIBLE,rcButton,200))
{
//设置按钮的图片
m_button1.SetBitmap(IDB_NORMAL,IDB_DOWN,IDB_BITMAP4,IDB_HOT);
}
.............
}
那么接下来重要的部分, 因为这个类没有窗体,只能依赖其他窗口实现自己的绘画和鼠标事件
对话框要实现自绘画功能就要重载BOOL OnEraseBkgnd(CDC* pDC)事件
普通窗口的话,只要重载void OnPaint() 事件
我们这里是对话框为主体,那么绘画部分就如下处理
BOOL CButtonDlg::OnEraseBkgnd(CDC* pDC)
{
BOOL bRet = CDialogEx::OnEraseBkgnd(pDC);
m_button1.Draw(pDC);
return bRet;
}
鼠标事件的实现如下:
void CButtonDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
m_button1.Track(point);
CDialogEx::OnLButtonDown(nFlags, point);
}
void CButtonDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
m_button1.Track(point);
CDialogEx::OnLButtonUp(nFlags, point);
}
void CButtonDlg::OnMouseMove(UINT nFlags, CPoint point)
{
m_button1.Track(point);
CDialogEx::OnMouseMove(nFlags, point);
}
请点击这里下载源码: ==> 源码下载