MFC 自绘button---基础篇

1.所谓自绘button,就是button的各种不同状态都需要我们自己绘制。

button的基本状态有:

鼠标在button外面,即鼠标离开button

鼠标悬浮在button上方,没有按下

鼠标按下button


2.用WM_MOUSELEAVE和WM_MOUSEMOVE来追踪鼠标在button外,还是鼠标在button里面。由于窗口是不响应 WM_MOUSELEAVE消息的,所以要使用 _TrackMouseEvent函数来激活这个消息。调用这个函数后,当鼠标离开窗口后,该函数会 Post 这个消息到指定窗口。

 OnMouseMove 中调用 _TrackMouseEvent 函数来不停的追踪WM_MOUSELEAVE消

{  
    if (!isinbutton)  
    {  
        TRACKMOUSEEVENT mouseevent;  
        mouseevent.cbSize=sizeof(mouseevent);  
        mouseevent.dwFlags=TME_LEAVE;  
        mouseevent.dwHoverTime=10;  
        mouseevent.hwndTrack=m_hWnd;  
        _TrackMouseEvent(&mouseevent);  
        isinbutton=true;  
        Invalidate();  
    }  
}  
isinbutton来判断鼠标是否在button窗口里


3.既然要自绘button,我们就自己写个CMyButton的类,该类派生于CButton 

CMyButton.h
#pragma once  
#ifndef _H_MYBUTTON_H  
#define _H_MYBUTTON_H  
  
  
class CMyButton : public CButton  
{  
    DECLARE_DYNAMIC(CMyButton)  
  
public:  
    CMyButton();     
    ~CMyButton();  
    virtual void PreSubclassWindow();  
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);  
    void FillRect(COLORREF color,CString text);  
    void ButtonLoadBitmap(CBitmap *cbitmap);  
  
  
protected:  
  
    afx_msg void OnMouseLeave();  
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  
    DECLARE_MESSAGE_MAP()  
  
private:  
    bool isinbutton; //鼠标是在button窗口里  
    bool isbuttondown; //button是否被按下  
    CRect rect;  
    CBitmap m_bmpNormal; //初始时button的位图  
    CBitmap m_bmpOn;    //鼠标悬浮在button上方时,button的位图  
    CBitmap m_bmpDown;  //按下button时,button的位图  
    CDC *dc;  
      
};  
#endif
  
CMyButton.cpp
#include "MyButtonDemo.h"  
#include "MyButton.h"  
#include <afx.h>  
  
  
IMPLEMENT_DYNAMIC(CMyButton, CButton)  
  
CMyButton::CMyButton()  
{  
    isinbutton=false;  
    isbuttondown=false;  
}  
  
CMyButton::~CMyButton()  
{  
}  
  
  
BEGIN_MESSAGE_MAP(CMyButton, CButton)  
    ON_WM_MOUSEMOVE()  
    ON_WM_MOUSELEAVE()  
    ON_WM_LBUTTONDOWN()  
    ON_WM_LBUTTONUP()  
END_MESSAGE_MAP()  
  
  
void CMyButton:: OnMouseMove(UINT nFlags, CPoint point)  
{  
    if (!isinbutton)  
    {  
        TRACKMOUSEEVENT mouseevent;  
        mouseevent.cbSize=sizeof(mouseevent);  
        mouseevent.dwFlags=TME_LEAVE;  
        mouseevent.dwHoverTime=10;  
        mouseevent.hwndTrack=m_hWnd;  
        _TrackMouseEvent(&mouseevent);  
        isinbutton=true;  
        Invalidate();//刷新button窗口,调用DrawItem函数来进行button重绘
}  
  
  
void CMyButton::OnMouseLeave()  
{  
    isinbutton=false;  
    isbuttondown=false;  
    Invalidate();//刷新button窗口,DrawItem函数来进行button重绘 
}  
  
void CMyButton::PreSubclassWindow()  
{  
    this->ModifyStyle(0, BS_OWNERDRAW);//修改为自绘button
    GetClientRect(&rect);  
    m_bmpNormal.LoadBitmap(IDB_BITMAP_NORMAL1);  
    m_bmpDown.LoadBitmap(IDB_BITMAP_ON2);  
    m_bmpOn.LoadBitmap(IDB_BITMAP_ON2);  
    dc=GetDC();  
    CButton::PreSubclassWindow();  
}  
  
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  
{  
      CString text=_T("");  
       if (isbuttondown)  //button被按下  
        {  
            isbuttondown=true;  
            ButtonLoadBitmap(&m_bmpDown);  
            text=_T("hover");  
            FillRect(RGB(255,0,0),text);  
        }  
        else if(isinbutton) //鼠标悬浮在button上方  
        {  
            ButtonLoadBitmap(&m_bmpOn);  
            text=_T("hover");  
            FillRect(RGB(0,255,0),text);  
        }  
        else  //鼠标在button窗口外  
        {  
            ButtonLoadBitmap(&m_bmpNormal);  
            text=_T("intal");  
            FillRect(RGB(0,0,255),text);      
        }  
}  
  
void CMyButton::FillRect(COLORREF color,CString text)  
{  
        //设置文字背景为透明   
    SetBkMode(dc->GetSafeHdc(),TRANSPARENT);   
    if (isbuttondown)  
    {  
        CRect rectdown=rect;  
        rectdown.OffsetRect(0,1); //button被按下,字体向下偏移1
        dc->DrawText (text,&rectdown,DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;  
    }  
    else  
       dc->DrawText(text,&rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;  
}  
  
void CMyButton::ButtonLoadBitmap(CBitmap *cbitmap)  
{  
    CDC   dcMem;     
    dcMem.CreateCompatibleDC(dc);   
    BITMAP   bitmap;     
    cbitmap->GetBitmap(&bitmap);   
    CBitmap   *pbmpOld=dcMem.SelectObject(cbitmap);    
    dc->SetStretchBltMode(HALFTONE);  
    dc->StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);      
    dcMem.SelectObject(pbmpOld);  
}  
  
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)  
{  
    isbuttondown=true;  
    Invalidate();//刷新button窗口,调用DrawItem函数来进行button重绘
}  
  
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)  
{  
    isbuttondown=FALSE;  
    Invalidate();//刷新button窗口,调用DrawItem函数来进行button重绘
}  


4.在对话框的OnInitDialog()函数中,将button控件子类化 
mybtn=new CMyButton; //mybtn已经定义为CMyButton*类型
mybtn->SubclassWindow(GetDlgItem(IDC_BUTTON_1)->GetSafeHwnd());
SubclassWindow函数非常重要,它将IDC_BUTTON_1窗口子类化,这样IDC_BUTTON_1窗口的消息,以后由CMyButton类来处理

5.完成以上几步,button就自绘成功啦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值