看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件。
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);
...
}
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)
...
ON_BN_CLICKED(1290,&CtestDlg::OnClickedOk)
END_MESSAGE_MAP()
void OnClickedOk();
void CtestDlg::OnClickedOk()
{
AfxMessageBox(_T("ok"));
}
代码很长,很多是自动生成的,主要的自绘过程都在OnPaint消息函数中完成。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。