1. 派生CButton
2. 重写PreSubclassWindow函数,设置BS_OWNERDRAW属性
void CButtonEx::PreSubclassWindow() {
// TODO: 在此添加专用代码和/或调用基类
UINT nStyle = GetButtonStyle();
SetButtonStyle(nStyle | BS_OWNERDRAW);
CButton::PreSubclassWindow();
}
3. 重写DrawItem函数实现Button重绘
ButtonEx.h
/* @Button自绘控件类设计 *根据鼠标动作绘制相对应的button形态 *鼠标动作:停止、按下、弹起 *button形态: */ #pragma once // CButtonEx class CButtonEx : public CButton { DECLARE_DYNAMIC(CButtonEx) public: CButtonEx(); virtual ~CButtonEx(); protected: DECLARE_MESSAGE_MAP() afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnCaptureChanged(CWnd *pWnd); afx_msg void OnMouseMove(UINT nFlags, CPoint point); virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void PreSubclassWindow(); void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect, BOOL IsPressed/*, BOOL IsDisabled*/); public: void SetIcon(int nIconInId, int nIconOutId = NULL, BYTE cx = 32, BYTE cy = 32); private: BOOL m_MouseOnButton; HICON m_hIconIn; HICON m_hIconOut; BYTE m_cyIcon; BYTE m_cxIcon; int m_nAlign; };
ButtonEx.cpp
// ButtonEx.cpp : 实现文件 // #include "stdafx.h" #include "mfcctrlstu.h" #include "ButtonEx.h" #include "ButtonBase.h" // CButtonEx IMPLEMENT_DYNAMIC(CButtonEx, CButton) CButtonEx::CButtonEx() { m_MouseOnButton = FALSE; m_nAlign = ST_ALIGN_HORIZ; } CButtonEx::~CButtonEx() { if (m_hIconIn != NULL) ::DeleteObject(m_hIconIn); if (m_hIconOut != NULL) ::DeleteObject(m_hIconOut); } BEGIN_MESSAGE_MAP(CButtonEx, CButton) ON_WM_MOUSEMOVE() ON_WM_KILLFOCUS() ON_WM_CAPTURECHANGED() END_MESSAGE_MAP() // CButtonEx 消息处理程序 void CButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect itemRect = lpDrawItemStruct->rcItem; BOOL bIsPressed = (lpDrawItemStruct->itemState & ODS_SELECTED); BOOL bIsFocused = (lpDrawItemStruct->itemState & ODS_FOCUS); BOOL bIsDisabled = (lpDrawItemStruct->itemState & ODS_DISABLED); CButtonBase *pButton = NULL; if (bIsPressed) { pButton = new CPressButton(); } else if (m_MouseOnButton) { pButton = new CMouseOnButton(); } else { pButton = new CFlatButton(); } // 属性初始化 CString strTitle=""; GetWindowText(strTitle); COLORREF color = RGB(255,0,0); pButton->SetButtonText(strTitle); pButton->SetBkColor(color); pButton->SetTextColor(color); pButton->SetIcon(m_hIconIn, m_hIconOut,m_cxIcon, m_cyIcon); pButton->SetGroupLignMode(m_nAlign); pButton->Draw(pDC, itemRect); delete pButton; pButton = NULL; } void CButtonEx::PreSubclassWindow() { // TODO: 在此添加专用代码和/或调用基类 UINT nStyle = GetButtonStyle(); SetButtonStyle(nStyle | BS_OWNERDRAW); CButton::PreSubclassWindow(); } void CButtonEx::OnMouseMove(UINT nFlags, CPoint point) { CWnd* pWnd; // Finestra attiva CWnd* pParent; // Finestra che contiene il bottone CButton::OnMouseMove(nFlags, point); // If the mouse enter the button with the left button pressed // then do nothing if (nFlags & MK_LBUTTON && m_MouseOnButton == FALSE) return; // If our button is not flat then do nothing //if (m_bIsFlat == FALSE) return; pWnd = GetActiveWindow(); pParent = GetOwner(); if ((GetCapture() != this) && ( #ifndef ST_LIKEIE pWnd != NULL && #endif pParent != NULL)) { m_MouseOnButton = TRUE; //SetFocus(); // Thanks Ralph! SetCapture(); Invalidate(); } else { CRect rc; GetClientRect(&rc); if (!rc.PtInRect(point)) { // Redraw only if mouse goes out if (m_MouseOnButton == TRUE) { m_MouseOnButton = FALSE; Invalidate(); } // If user is NOT pressing left button then release capture! if (!(nFlags & MK_LBUTTON)) ReleaseCapture(); } } } void CButtonEx::OnKillFocus(CWnd* pNewWnd) { CButton::OnKillFocus(pNewWnd); // If our button is not flat then do nothing //if (m_bIsFlat == FALSE) return; if (m_MouseOnButton == TRUE) { m_MouseOnButton = FALSE; Invalidate(); } } void CButtonEx::OnCaptureChanged(CWnd *pWnd) { if (m_MouseOnButton == TRUE) { ReleaseCapture(); Invalidate(); } // Call base message handler CButton::OnCaptureChanged(pWnd); } // End of OnCaptureChanged void CButtonEx::SetIcon(int nIconInId, int nIconOutId, BYTE cx, BYTE cy) { HINSTANCE hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconInId),RT_GROUP_ICON); // Set icon when the mouse is IN the button m_hIconIn = (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconInId), IMAGE_ICON, 0, 0, 0); // Set icon when the mouse is OUT the button m_hIconOut = (nIconOutId == NULL) ? m_hIconIn : (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconOutId), IMAGE_ICON, 0, 0, 0); m_cxIcon = cx; m_cyIcon = cy; RedrawWindow(); } // End of SetIcon void CButtonEx::DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect, BOOL IsPressed/*, BOOL IsDisabled*/) { CRect iconRect = rcItem; // 根据对齐方式进行布局 switch (m_nAlign) { case ST_ALIGN_HORIZ: if (title->IsEmpty()) { // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); } else { // L‘icona deve vedersi subito dentro il focus rect iconRect.left += 3; captionRect->left += m_cxIcon + 3; } // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); break; case ST_ALIGN_VERT: // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); if (title->IsEmpty()) { // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); } else { captionRect->top += m_cyIcon; } break; } // If button is pressed then press the icon also if (IsPressed) iconRect.OffsetRect(1, 1); // Ole‘! pDC->DrawState(iconRect.TopLeft(), iconRect.Size(), (m_MouseOnButton == TRUE || IsPressed) ? m_hIconIn : m_hIconOut, DSS_NORMAL, /*(IsDisabled ? DSS_DISABLED : DSS_NORMAL), */ (CBrush*)NULL); } // End of DrawTheIcon
ButtonBase.h
/* * */ #pragma once enum TEXT_ICON_ALIGN { ST_ALIGN_HORIZ = 0, ST_ALIGN_VERT }; class CButtonBase { public: CButtonBase(){}; virtual ~CButtonBase(){}; virtual void Draw(CDC *pDC, CRect itemRect) = 0; // button绘制 virtual void SetButtonText(CString StrText)=0; virtual void SetBkColor(COLORREF color)=0; virtual void SetTextColor(COLORREF color)=0; virtual void SetIcon(HICON hIconIn=NULL, HICON hIconOut=NULL, BYTE m_cyIcon=32,BYTE m_cxIcon=32)=0; virtual void SetGroupLignMode(int nAlignType = ST_ALIGN_HORIZ)=0; protected: CString m_strText; // 文本内容 COLORREF m_bkColor; // 背景色 COLORREF m_TextColor; // 文本颜色 HICON m_hIconIn; // 图标1 HICON m_hIconOut; // 图标2; BYTE m_cyIcon; BYTE m_cxIcon; int m_nAlign; // 文本、icon对齐方式 }; class CMouseOnButton : public CButtonBase { public: CMouseOnButton(); virtual ~CMouseOnButton(); void Draw(CDC *pDC, CRect itemRect); void SetButtonText(CString StrText){m_strText=StrText;} void SetBkColor(COLORREF color){m_bkColor=color;} void SetTextColor(COLORREF color){m_TextColor=color;} void SetIcon(HICON hIconIn=NULL, HICON hIconOut=NULL,BYTE cyIcon=32,BYTE cxIcon=32) { m_hIconIn=hIconIn; m_hIconOut=hIconOut; m_cxIcon = cxIcon; m_cyIcon = cyIcon; } void SetGroupLignMode(int nAlignType = ST_ALIGN_HORIZ){m_nAlign=nAlignType;} private: void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect); }; class CFlatButton : public CButtonBase { public: CFlatButton(); virtual ~CFlatButton(); void Draw(CDC *pDC, CRect itemRect); void SetButtonText(CString StrText){m_strText=StrText;} void SetBkColor(COLORREF color){m_bkColor=color;} void SetTextColor(COLORREF color){m_TextColor=color;} void SetIcon(HICON hIconIn=NULL, HICON hIconOut=NULL,BYTE cyIcon=32,BYTE cxIcon=32) { m_hIconIn=hIconIn; m_hIconOut=hIconOut; m_cxIcon = cxIcon; m_cyIcon = cyIcon; } void SetGroupLignMode(int nAlignType = ST_ALIGN_HORIZ){m_nAlign=nAlignType;} private: void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect); }; class CPressButton : public CButtonBase { public: CPressButton(); virtual ~CPressButton(); void Draw(CDC *pDC, CRect itemRect); void SetButtonText(CString StrText){m_strText=StrText;} void SetBkColor(COLORREF color){m_bkColor=color;} void SetTextColor(COLORREF color){m_TextColor=color;} void SetIcon(HICON hIconIn=NULL, HICON hIconOut=NULL,BYTE cyIcon=32,BYTE cxIcon=32) { m_hIconIn=hIconIn; m_hIconOut=hIconOut; m_cxIcon = cxIcon; m_cyIcon = cyIcon; } void SetGroupLignMode(int nAlignType = ST_ALIGN_HORIZ){m_nAlign=nAlignType;} private: void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect); };
ButtonBase.cpp
#include "stdafx.h" #include "ButtonBase.h" // 平按钮类实现 CFlatButton::CFlatButton() { m_strText = ""; m_bkColor = RGB(0,0,0); m_TextColor = RGB(0,0,0); m_hIconIn = NULL; m_hIconOut = NULL; m_cyIcon = 32; m_cxIcon = 32; m_nAlign = 0; } CFlatButton::~CFlatButton() { } void CFlatButton::Draw( CDC *pDC, CRect itemRect ) { itemRect.DeflateRect(1,1); CPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black CPen *pOldPen = pDC->SelectObject(&pen3DDKShadow); //CBrush bkBrush(m_bkColor); //pDC->FillRect(&itemRect, &bkBrush); CRect rcICon = itemRect; DrawTheIcon(pDC, &m_strText, &rcICon,&itemRect); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(m_strText, &itemRect,DT_SINGLELINE|DT_CENTER); pDC->SetTextColor(m_TextColor); pDC->SelectObject(pOldPen); } void CFlatButton::DrawTheIcon( CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect ) { CRect iconRect = rcItem; // 根据对齐方式进行布局 switch (m_nAlign) { case ST_ALIGN_HORIZ: if (title->IsEmpty()) { // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); } else { // L‘icona deve vedersi subito dentro il focus rect iconRect.left += 3; captionRect->left += m_cxIcon + 3; } // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); break; case ST_ALIGN_VERT: // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); if (title->IsEmpty()) { // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); } else { captionRect->top += m_cyIcon; } break; } pDC->DrawState(iconRect.TopLeft(), iconRect.Size(), m_hIconOut, DSS_NORMAL,(CBrush*)NULL); } CMouseOnButton::CMouseOnButton() { m_strText = ""; m_bkColor = RGB(0,0,0); m_TextColor = RGB(0,0,0); m_hIconIn = NULL; m_hIconOut = NULL; m_cyIcon = 32; m_cxIcon = 32; m_nAlign = 0; } CMouseOnButton::~CMouseOnButton() { } void CMouseOnButton::Draw( CDC *pDC, CRect itemRect) { CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // White CPen pen3DLight(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT)); // Light gray CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW)); // Dark gray CPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black CPen *pOldPen = pDC->SelectObject(&penBtnHiLight); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.left, itemRect.top); pDC->LineTo(itemRect.right, itemRect.top); // Disegno i bordi a destra e in basso // Dark gray line pDC->SelectObject(penBtnShadow); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.top-1); itemRect.DeflateRect(1,1); pDC->SelectObject(&pen3DDKShadow); //CBrush bkBrush(m_bkColor); //pDC->FillRect(&itemRect, &bkBrush); CRect rcICon = itemRect; DrawTheIcon(pDC, &m_strText, &rcICon,&itemRect); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(m_strText, &itemRect,DT_SINGLELINE|DT_CENTER); pDC->SetTextColor(m_TextColor); pDC->SelectObject(pOldPen); } void CMouseOnButton::DrawTheIcon( CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect ) { CRect iconRect = rcItem; // 根据对齐方式进行布局 switch (m_nAlign) { case ST_ALIGN_HORIZ: if (title->IsEmpty()) { // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); } else { // L‘icona deve vedersi subito dentro il focus rect iconRect.left += 3; captionRect->left += m_cxIcon + 3; } // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); break; case ST_ALIGN_VERT: // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); if (title->IsEmpty()) { // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); } else { captionRect->top += m_cyIcon; } break; } pDC->DrawState(iconRect.TopLeft(), iconRect.Size(), m_hIconOut, DSS_NORMAL,(CBrush*)NULL); } // PressButton类实现 CPressButton::CPressButton() { m_strText = ""; m_bkColor = RGB(0,0,0); m_TextColor = RGB(0,0,0); m_hIconIn = NULL; m_hIconOut = NULL; m_cyIcon = 32; m_cxIcon = 32; m_nAlign = 0; } CPressButton::~CPressButton() { } void CPressButton::Draw( CDC *pDC, CRect itemRect ) { CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // Bianco CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW)); // Grigio scuro // Disegno i bordi a sinistra e in alto // Dark gray line CPen *pOldPen = pDC->SelectObject(&penBtnShadow); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.left, itemRect.top); pDC->LineTo(itemRect.right, itemRect.top); // Disegno i bordi a destra e in basso // White line pDC->SelectObject(penBtnHiLight); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.top-1); itemRect.DeflateRect(1,1); // pDC->SelectObject(&pen3DDKShadow); //CBrush bkBrush(m_bkColor); //pDC->FillRect(&itemRect, &bkBrush); CRect rcICon = itemRect; DrawTheIcon(pDC, &m_strText, &rcICon,&itemRect); pDC->SetBkMode(TRANSPARENT); pDC->DrawText(m_strText, &itemRect,DT_SINGLELINE|DT_CENTER); pDC->SetTextColor(m_TextColor); pDC->SelectObject(pOldPen); } void CPressButton::DrawTheIcon( CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect ) { CRect iconRect = rcItem; // 根据对齐方式进行布局 switch (m_nAlign) { case ST_ALIGN_HORIZ: if (title->IsEmpty()) { // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); } else { // L‘icona deve vedersi subito dentro il focus rect iconRect.left += 3; captionRect->left += m_cxIcon + 3; } // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); break; case ST_ALIGN_VERT: // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); if (title->IsEmpty()) { // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); } else { captionRect->top += m_cyIcon; } break; } pDC->DrawState(iconRect.TopLeft(), iconRect.Size(), m_hIconIn, DSS_NORMAL,(CBrush*)NULL); }