这是一个按钮自绘的框架,其他控件也类似

//.h头文件
#pragma once
#include "afxwin.h"
#include "MemDC.h"//封装内存DC类

class CYuButton :public CWnd
{
    private:
		BOOL  m_bIsDown;
		BOOL  m_bIsMove;
		BOOL  _bMouseTrack;

		CString  m_sCaption;
		CFont    *m_pFont;
		
		
        INT    m_nFocusPic;//焦点图片
		INT    m_nForePic; //前景图片

		CMemoryDC  m_Icon_MDC;
		CMemoryDC  m_focus_MDC;
		CMemoryDC  m_fore_MDC;

		CMemoryDC  m_CompoundDC;//合成位图DC

		bool m_bTracking = TRUE;
    public:
        DECLARE_DYNCREATE(CYuButton)
		CYuButton(void);
		virtual ~CYuButton(void);

		BOOL Create(LPCTSTR strCaption,const CRect &rt,CWnd * 
		            pParendWnd,UINT uId,UINT strFocusPic,UINT strForePic);
			
		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 OnKillFocus(CWnd* pNewWnd);
        DECLARE_MESSAGE_MAP()

		//鼠标按下
		void DrawDown(CDC * pDC);
		void DrawNormal(CDC * pDC);
		//鼠标移动
		void DrawMove(CDC * pDC);
		//字体
		void SetFont(CFont * pFont);
		CFont * GetFont();
		
		//获取当前程序路径
		CString  GetApplicationPath();
public:
		//修改按钮状态
		void SetNormalStatus();
		afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
		afx_msg void OnMouseHover(UINT nFlags, CPoint point);
		afx_msg void OnMouseMove(UINT nFlags, CPoint point);
		afx_msg void OnMouseLeave();
		afx_msg void OnSetFocus(CWnd* pOldWnd);
		afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
};
//.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 strCaption,const CRect &rt,CWnd * pParendWnd,
     UINT uId,UINT strFocusPic,UINT strForePic)
{
LPCTSTR lpszClassName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | WS_TABSTOP,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)GetStockObject(LTGRAY_BRUSH), NULL);

m_sCaption    = strCaption;
m_nFocusPic = strFocusPic;
m_nForePic  = strForePic;

BOOL re = m_Icon_MDC.LoadBitmap(m_nForePic);
    re = m_focus_MDC.LoadBitmap(m_nFocusPic);//画焦点图片85*110
    re = m_fore_MDC.LoadBitmap(m_nForePic);  //显示图标

m_CompoundDC.Create(m_focus_MDC.Width(),m_focus_MDC.Height());//空白内存位图

m_pFont = pParendWnd->GetFont();
return CWnd::Create(lpszClassName,strCaption,WS_VISIBLE|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);
}

IMPLEMENT_DYNCREATE(CYuButton, CWnd)
BEGIN_MESSAGE_MAP(CYuButton, CWnd)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDBLCLK()
ON_WM_MOUSEHOVER()
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
ON_WM_SETFOCUS()
ON_WM_KEYDOWN()
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

if(m_bIsDown)
     DrawNormal(&dc);	
else
     DrawDown(&dc);


//绘按钮上面的文字
CRect rt;
GetClientRect(&rt);
   rt.top = 69;

   dc.SetTextColor(RGB(0,120,215));
  
   CFont font;
VERIFY(font.CreatePointFont(90,_T("微软雅黑"), &dc));

CFont * pOldFont = dc.SelectObject(&font);
dc.SetBkMode(TRANSPARENT);
rt.top = 40;
dc.DrawText(m_sCaption,rt,DT_CENTER);

dc.SelectObject(pOldFont);

}

void CYuButton::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
   CWnd::OnLButtonDown(nFlags, point);
m_bIsDown = TRUE;
this->Invalidate(FALSE);
SetFocus();
//TRACE(_T("点击按钮!\n"));
}

void CYuButton::OnLButtonUp(UINT nFlags, CPoint point)
{
CWnd::OnLButtonUp(nFlags, point);
CWnd * pWnd = this->GetParent();
if (pWnd)
pWnd->SendMessage(WM_COMMAND, GetDlgCtrlID(), (LPARAM)this->GetSafeHwnd());
}

void CYuButton::DrawNormal(CDC * pDC)
{
//m_CompoundDC.BitBlt(0,0,m_focus_MDC.Width(),m_focus_MDC.Height(),
//&m_focus_MDC,0,0,SRCCOPY);
//m_fore_MDC.BitTrans(0,0,m_fore_MDC.Width(),m_fore_MDC.Height(),
//&m_CompoundDC,0,0,RGB(135,200,241));
//pDC->BitBlt(0,0,m_focus_MDC.Width(),m_focus_MDC.Height(),
//&m_CompoundDC,0,0,SRCCOPY);
pDC->BitBlt(0, 0, m_Icon_MDC.Width(), m_Icon_MDC.Height(),
&m_fore_MDC, 0, 0, SRCCOPY);
}

void CYuButton::DrawDown(CDC * pDC)
{
//画小图标
// CBrush  br(RGB(221, 203, 255));
// CBrush * pOldBrush =  pDC->SelectObject(&br);
// CRect rect(0, 0, m_Icon_MDC.Width(), m_Icon_MDC.Height());
// pDC->FillRect(&rect,&br);

pDC->BitBlt(0,0,m_Icon_MDC.Width(),m_Icon_MDC.Height(),&m_focus_MDC,0,0,SRCCOPY);

//pDC->SelectObject(pOldBrush);
}

void CYuButton::SetFont(CFont * pFont)
{
m_pFont = pFont;
}

CFont * CYuButton::GetFont()
{
   return m_pFont;
}

void CYuButton::OnKillFocus(CWnd* pNewWnd)
{
CWnd::OnKillFocus(pNewWnd);
m_bIsDown = FALSE;
Invalidate(TRUE);
}

CString CYuButton::GetApplicationPath()
{
WCHAR  buff[255]={0};
::GetModuleFileName(0,buff,255);

CString strAppFullName;
strAppFullName.Format(_T("%s"),buff);

CString strAppPath = _T("");
strAppPath = strAppFullName.Left(strAppFullName.ReverseFind('\\')+1);
return strAppPath;
}

void CYuButton::SetNormalStatus()
{
   m_bIsDown = FALSE;
Invalidate(FALSE);
}

void CYuButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//CWnd * pWnd = this->GetParent();
//if (pWnd)
//pWnd->SendMessage(WM_COMMAND, GetDlgCtrlID(), (LPARAM)this->GetSafeHwnd());
CWnd::OnLButtonDblClk(nFlags, point);
}

void CYuButton::OnMouseHover(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bIsDown = TRUE;
Invalidate();
CWnd::OnMouseHover(nFlags, point);
}

void CYuButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TRACKMOUSEEVENT  tme = { 0 };
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = 50;
tme.hwndTrack = this->m_hWnd;
if (TrackMouseEvent(&tme)) {}

CWnd::OnMouseMove(nFlags, point);
}

void CYuButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bIsDown = FALSE;
Invalidate();
CWnd::OnMouseLeave();
}


void CYuButton::OnSetFocus(CWnd* pOldWnd)
{
m_bIsDown = TRUE;
Invalidate();
   CWnd::OnSetFocus(pOldWnd);
// TODO: 在此处添加消息处理程序代码
}


void CYuButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}