我们继续来了解MFC控件的基本使用, 按钮的使用大家肯定都很熟悉了, 我们今天来了解一下Button按钮的功能扩展怎么实现。
我们来看头文件代码:
#pragma once
// CMyButton
class CMyButton : public CButton
{
DECLARE_DYNAMIC(CMyButton)
public:
CMyButton();
virtual ~CMyButton();
CFont m_fontMouseMove; //鼠标移动到按钮上时用的字体
HCURSOR m_hCurSorMouseMove; //鼠标移动到按钮上时用的光标
BOOL m_isLButtonDown; //鼠标左键是否按下
BOOL m_isMouseInButton; //鼠标是否在按钮上面
protected:
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);//绘制控件消息
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//左键按下消息
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);//左键抬起消息
afx_msg void OnMouseMove(UINT nFlags, CPoint point);//鼠标移动
afx_msg void OnTimer(UINT_PTR nIDEvent);//计时器
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);//设置光标
};
下面是函数实现:
// CMyButton.cpp: 实现文件
//
#include "pch.h"
#include "class08.h"
#include "CMyButton.h"
// CMyButton
IMPLEMENT_DYNAMIC(CMyButton, CButton)
CMyButton::CMyButton()
{
}
CMyButton::~CMyButton()
{
}
BEGIN_MESSAGE_MAP(CMyButton, CButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
// CMyButton 消息处理程序
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
//整个按钮的外观都是在这里进行绘制
CDC* pDc = CDC::FromHandle(lpDrawItemStruct->hDC);//获取dc
CRect rect(lpDrawItemStruct->rcItem);//按钮的rect结构
pDc->SetBkMode(TRANSPARENT);
UINT buttonState = lpDrawItemStruct->itemState;//获取按钮状态
CFont* pOldFont = NULL;
CString strText;
GetWindowText(strText);
if (m_isMouseInButton)
{
if (buttonState & ODS_SELECTED)//判断有没有点击按钮
{
pDc->Draw3dRect(rect,//指定范围内的矩形
GetSysColor(COLOR_3DSHADOW),//三维矩形的顶部和左侧的颜色
GetSysColor(COLOR_3DHILIGHT)//三维矩形的底部和右侧的颜色
);
}
else
pDc->Draw3dRect(rect, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW));
pDc->SetTextColor(RGB(255, 0, 0));
if (m_fontMouseMove.GetSafeHandle() == NULL)
{
CFont* font = GetFont();
LOGFONT lf;
font->GetLogFont(&lf);
lf.lfUnderline = true;
m_fontMouseMove.CreateFontIndirect(&lf);
}
pOldFont = pDc->SelectObject(&m_fontMouseMove);
}
else
{
pDc->SetTextColor(RGB(0, 0, 0));
}
pDc->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
if (pOldFont)
pDc->SelectObject(pOldFont);
// TODO: 添加您的代码以绘制指定项
}
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_isLButtonDown = true;
CButton::OnLButtonDown(nFlags, point);
}
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_isLButtonDown = false;
if (m_isMouseInButton)
{
m_isMouseInButton = false;
InvalidateRect(NULL);//整个按钮的区域无效
}
CButton::OnLButtonUp(nFlags, point);
}
void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
SetTimer(1, 10, NULL);
CButton::OnMouseMove(nFlags, point);
}
void CMyButton::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
static BOOL bPainted = false; //防止重绘用的
POINT pt;
GetCursorPos(&pt);//获取鼠标关于屏幕的位置
CRect rect;
GetWindowRect(&rect);//获得CWnd的屏幕坐标
if (m_isLButtonDown)
{
KillTimer(1);
return;
}
if (!rect.PtInRect(pt))//判断光标的坐标在不在按钮的矩形区域内
{
m_isMouseInButton = false;
KillTimer(1);
if (bPainted)
InvalidateRect(NULL);
bPainted = false;
return;
}
else
{
m_isMouseInButton = true;
if (!bPainted)
{
bPainted = true;
InvalidateRect(NULL);
}
}
CButton::OnTimer(nIDEvent);
}
BOOL CMyButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_isMouseInButton)
{
::SetCursor(::LoadCursorFromFile(_T("res\\CURSOR1.CUR")));
}
//return CButton::OnSetCursor(pWnd, nHitTest, message);//需要注释掉
return true;
}