VC自绘按钮

来源:互联网 发布:超市销售量的数据 编辑:程序博客网 时间:2024/06/05 02:02
看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件。
YuButton.h头文件如下:
#pragma once#include "afxwin.h"class CYuButton :public CWnd{    private:BOOL  m_bIsDown;BOOL  m_bIsMove;BOOL  _bMouseTrack;//鼠标追踪状态CString  m_sCaption;CFont    *m_pFont;    public:CYuButton(void);virtual ~CYuButton(void);BOOL Create(LPCTSTR sCpation,DWORD dwStyle,CONST CRect & rt,CWnd * pParendWnd,                   UINT uId);BOOL CreateEx(DWORD dwExStyle,LPCTSTR sCaption,DWORD dwStyle,CONST CRect & rt,CWnd * pParendWnd,UINT uId);DECLARE_MESSAGE_MAP()afx_msg void OnNcPaint();afx_msg BOOL OnEraseBkgnd(CDC* pDC);afx_msg void OnPaint();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);//鼠标按下void DrawDown(CDC * pDC);//鼠标移动void DrawMove(CDC * pDC);//字体void SetFont(CFont * pFont);CFont * GetFont();afx_msg void OnKillFocus(CWnd* pNewWnd);afx_msg void OnMouseHover(UINT nFlags, CPoint point);afx_msg void OnMouseLeave();};
YuButton.cpp文件内容如下:
#include "StdAfx.h"#include "YuButton.h"CYuButton::CYuButton(void){WNDCLASS wd={CS_VREDRAW|CS_HREDRAW,::DefWindowProc};wd.lpszClassName = _T("YUButton");AfxRegisterClass(&wd);m_bIsDown   = FALSE;m_bIsMove   = FALSE;_bMouseTrack = TRUE;}CYuButton::~CYuButton(void){}BOOL CYuButton::Create(LPCTSTR sCaption,DWORD dwStyle,CONST CRect & rt,CWnd *pParendWnd,UINT uId){m_sCaption = sCaption;m_pFont = pParendWnd->GetFont();return CWnd::Create(_T("YUButton"),sCaption,dwStyle|WS_CHILD,rt,pParendWnd,uId);}BOOL CYuButton::CreateEx(DWORD dwExStyle,LPCTSTR sCaption,DWORD dwStyle,CONST CRect & rt,CWnd * pParendWnd,UINT uId){m_sCaption = sCaption;return CWnd::CreateEx(dwExStyle,_T("YUButton"),sCaption,dwStyle|WS_CHILD,rt,                          pParendWnd,uId);}BEGIN_MESSAGE_MAP(CYuButton, CWnd)ON_WM_NCPAINT()ON_WM_ERASEBKGND()ON_WM_PAINT()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_KILLFOCUS()ON_WM_MOUSEHOVER()ON_WM_MOUSELEAVE()END_MESSAGE_MAP()void CYuButton::OnNcPaint(){}BOOL CYuButton::OnEraseBkgnd(CDC* pDC){return true;//CWnd::OnEraseBkgnd(pDC);}void CYuButton::OnPaint(){CPaintDC dc(this); // device context for paintingCRect rt;GetClientRect(&rt);if(!m_bIsDown )//未点击填充{CBrush brush(RGB(241,243,248));dc.SelectObject(brush);dc.FillRect(rt,&brush);}elseDrawDown(&dc);if(m_bIsMove && !m_bIsDown)//鼠标移动{DrawMove(&dc);}CPen pen;//画边框pen.CreatePen(PS_SOLID,1,RGB(85,134,233));dc.SelectObject(pen);dc.Rectangle(rt);dc.SelectObject(m_pFont);//父窗口字体dc.SetBkMode(TRANSPARENT);dc.DrawText(m_sCaption,rt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);}void CYuButton::OnLButtonDown(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值m_bIsDown = TRUE;    this->SetFocus();this->Invalidate(TRUE);CWnd::OnLButtonDown(nFlags, point);}void CYuButton::OnLButtonUp(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值m_bIsDown = FALSE;this->Invalidate(TRUE);CWnd * pWnd = this->GetParent();if(pWnd)pWnd->SendMessage(WM_COMMAND,GetDlgCtrlID(),(LPARAM)this->GetSafeHwnd());CWnd::OnLButtonUp(nFlags, point);}void CYuButton::OnMouseMove(UINT nFlags, CPoint point){if (_bMouseTrack)     //若允许追踪,则。 {TRACKMOUSEEVENT csTME;csTME.cbSize = sizeof (csTME);csTME.dwFlags = TME_LEAVE|TME_HOVER;csTME.hwndTrack = m_hWnd ;// 指定要追踪的窗口 csTME.dwHoverTime = 10;  // 鼠标在按钮上停留超过 10ms ,才认为状态为 HOVER::_TrackMouseEvent (&csTME); //开启 Windows 的 WM_MOUSELEAVE,WM_MOUSEHOVER 事件支持_bMouseTrack=FALSE ;   // 若已经追踪,则停止追踪 }CWnd::OnMouseMove(nFlags, point);}void CYuButton::DrawDown(CDC * pDC){CRect rt;GetClientRect(&rt);CBrush brush;brush.CreateSolidBrush(RGB(124,180,233));pDC->SelectObject(brush);pDC->FillRect(rt,&brush);}void CYuButton::SetFont(CFont * pFont){m_pFont = pFont;}CFont * CYuButton::GetFont(){    return m_pFont;}void CYuButton::DrawMove(CDC * pDC){CRect rt;GetClientRect(&rt);CBrush brush;brush.CreateSolidBrush(RGB(188,199,216));pDC->SelectObject(brush);pDC->FillRect(rt,&brush);}void CYuButton::OnKillFocus(CWnd* pNewWnd){CWnd::OnKillFocus(pNewWnd);m_bIsMove = FALSE;Invalidate(TRUE);}void CYuButton::OnMouseHover(UINT nFlags, CPoint point){m_bIsMove = TRUE;Invalidate(TRUE);CWnd::OnMouseHover(nFlags, point);}void CYuButton::OnMouseLeave(){_bMouseTrack = TRUE;m_bIsMove = FALSE;Invalidate(TRUE);CWnd::OnMouseLeave();}
在对话框窗口头文件中声明:CYuButton m_ok成员变量,然后OnInitDialog函数中创建自绘按钮:
(注意:对话框窗口头文件,须包含自绘按钮控件的.h文件YuButton.h)
BOOL CtestDlg::OnInitDialog(){    ...    CRect rc(20,20,120,43);    m_ok.Create(_T("确定"),WS_VISIBLE,rc,this,1290);    ...}
手动添加消息映射,为什么手动,因为自绘按钮,其ID不在资源中,所以不能用类向导管理,如下:
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)   ...   ON_BN_CLICKED(1290,&CtestDlg::OnClickedOk)END_MESSAGE_MAP()
对话框窗口头文件中,声明相应的消息处理函数OnClickedOk,如下:
void OnClickedOk();
编写消息处理函数代码:
void CtestDlg::OnClickedOk(){AfxMessageBox(_T("ok"));}


代码很长,很多是自动生成的,主要的自绘过程都在OnPaint消息函数中完成。

原创粉丝点击