VC自绘按钮

看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件。
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 painting
	CRect rt;
	GetClientRect(&rt);
	
	if(!m_bIsDown )//未点击填充
	{
		CBrush brush(RGB(241,243,248));
		dc.SelectObject(brush);
		dc.FillRect(rt,&brush);
	}
	else
		DrawDown(&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消息函数中完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值