看了呂鑫老師的視頻,自己試著編寫了一個(gè)自繪按鈕控件。
YuButton.h頭文件如下:
#pragma once #include "afxwin.h" class CYuButton :public CWnd { private: BOOL m_bIsDown; BOOL m_bIsMove; BOOL _bMouseTrack;//鼠標(biāo)追蹤狀態(tài) 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); //鼠標(biāo)按下 void DrawDown(CDC * pDC); //鼠標(biāo)移動(dòng) 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文件內(nèi)容如下:
#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 )//未點(diǎn)擊填充 { CBrush brush(RGB(241,243,248)); dc.SelectObject(brush); dc.FillRect(rt,&brush); } else DrawDown(&dc); if(m_bIsMove && !m_bIsDown)//鼠標(biāo)移動(dòng) { 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: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值 m_bIsDown = TRUE; this->SetFocus(); this->Invalidate(TRUE); CWnd::OnLButtonDown(nFlags, point); } void CYuButton::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值 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; // 鼠標(biāo)在按鈕上停留超過 10ms ,才認(rèn)為狀態(tài)為 HOVER ::_TrackMouseEvent (&csTME); //開啟 Windows 的 WM_MOUSELEAVE,WM_MOUSEHOVER 事件支持 _bMouseTrack=FALSE ; // 若已經(jīng)追蹤,則停止追蹤 } 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(); }
在對(duì)話框窗口頭文件中聲明:CYuButton m_ok成員變量,然后OnInitDialog函數(shù)中創(chuàng)建自繪按鈕:
(注意:對(duì)話框窗口頭文件,須包含自繪按鈕控件的.h文件YuButton.h)
BOOL CtestDlg::OnInitDialog() { ... CRect rc(20,20,120,43); m_ok.Create(_T("確定"),WS_VISIBLE,rc,this,1290); ... }
手動(dòng)添加消息映射,為什么手動(dòng),因?yàn)樽岳L按鈕,其ID不在資源中,所以不能用類向?qū)Ч芾?,如下?/p>
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx) ... ON_BN_CLICKED(1290,&CtestDlg::OnClickedOk) END_MESSAGE_MAP()
對(duì)話框窗口頭文件中,聲明相應(yīng)的消息處理函數(shù)OnClickedOk,如下:
void OnClickedOk();
編寫消息處理函數(shù)代碼:
void CtestDlg::OnClickedOk() { AfxMessageBox(_T("ok")); }
代碼很長(zhǎng),很多是自動(dòng)生成的,主要的自繪過程都在OnPaint消息函數(shù)中完成。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。