⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 roundbutton.cpp

📁 利用VC++开发环境
💻 CPP
字号:
//   RoundButton.cpp文件   

/////////////////////////////////////////////////////////////////////////////   

#include   "stdafx.h"   
#include   "math.h"   
#include   "RoundButton.h"   

#ifdef   _DEBUG   
#define   new   DEBUG_NEW   
#undef   THIS_FILE   
static   char   THIS_FILE[]   =   __FILE__;   
#endif   

//   prototypes   
COLORREF   GetColour(double   dAngle,   COLORREF   crBright,   COLORREF   crDark);   
void   DrawCircle(CDC*   pDC,   CPoint   p,   LONG   lRadius,   COLORREF   crColour,   BOOL   bDashed   =   FALSE);   
void   DrawCircle(CDC*   pDC,   CPoint   p,   LONG   lRadius,   COLORREF   crBright,   COLORREF   crDark);   


//   Calculate   colour   for   a   point   at   the   given   angle   by   performing   a   linear   
//   interpolation   between   the   colours   crBright   and   crDark   based   on   the   cosine   
//   of   the   angle   between   the   light   source   and   the   point.   
//   
//   Angles   are   measured   from   the   +ve   x-axis   (i.e.   (1,0)   =   0   degrees,   (0,1)   =   90   degrees   )   
//   But   remember:   +y   points   down!   

COLORREF   GetColour(double   dAngle,   COLORREF   crBright,   COLORREF   crDark)   
{   
#define   Rad2Deg 180.0/3.1415     
#define   LIGHT_SOURCE_ANGLE -2.356 //   -2.356   radians   =   -135   degrees,   i.e.   From   top   left   
    
	ASSERT(dAngle   >   -3.1416   &&   dAngle   <   3.1416);   
	double   dAngleDifference   =   LIGHT_SOURCE_ANGLE   -   dAngle;   
    
	if   (dAngleDifference   <   -3.1415)   dAngleDifference   =   6.293   +   dAngleDifference;   
	else   if   (dAngleDifference   >   3.1415)   dAngleDifference   =   6.293   -   dAngleDifference;   
    
	double   Weight   =   0.5*(cos(dAngleDifference)+1.0);   
    
	BYTE   Red       =   (BYTE)   (Weight*GetRValue(crBright)   +   (1.0-Weight)*GetRValue(crDark));   
	BYTE   Green   =   (BYTE)   (Weight*GetGValue(crBright)   +   (1.0-Weight)*GetGValue(crDark));   
	BYTE   Blue     =   (BYTE)   (Weight*GetBValue(crBright)   +   (1.0-Weight)*GetBValue(crDark));   
    
	//TRACE("LightAngle   =   %0.0f,   Angle   =   %3.0f,   Diff   =   %3.0f,   Weight   =   %0.2f,   RGB   %3d,%3d,%3d\n",     
	//     LIGHT_SOURCE_ANGLE*Rad2Deg,   dAngle*Rad2Deg,   dAngleDifference*Rad2Deg,   Weight,Red,Green,Blue);   
    
	return   RGB(Red,   Green,   Blue);   
}   

void   DrawCircle(CDC*   pDC,   CPoint   p,   LONG   lRadius,   COLORREF   crColour,   BOOL   bDashed)   
{   
	const   int   nDashLength   =   1;   
	LONG   lError,   lXoffset,   lYoffset;   
	int     nDash   =   0;   
	BOOL   bDashOn   =   TRUE;   
    
	//Check   to   see   that   the   coordinates   are   valid   
	ASSERT(   (p.x   +   lRadius   <=   LONG_MAX)   &&   (p.y   +   lRadius   <=   LONG_MAX)   );   
	ASSERT(   (p.x   -   lRadius   >=   LONG_MIN)   &&   (p.y   -   lRadius   >=   LONG_MIN)   );   
    
	//Set   starting   values   
	lXoffset   =   lRadius;   
	lYoffset   =   0;   
	lError       =   -lRadius;   
    
	do   {   
		if   (bDashOn)   {   
			pDC->SetPixelV(p.x   +   lXoffset,   p.y   +   lYoffset,   crColour);   
			pDC->SetPixelV(p.x   +   lXoffset,   p.y   -   lYoffset,   crColour);   
			pDC->SetPixelV(p.x   +   lYoffset,   p.y   +   lXoffset,   crColour);   
			pDC->SetPixelV(p.x   +   lYoffset,   p.y   -   lXoffset,   crColour);   
			pDC->SetPixelV(p.x   -   lYoffset,   p.y   +   lXoffset,   crColour);   
			pDC->SetPixelV(p.x   -   lYoffset,   p.y   -   lXoffset,   crColour);   
			pDC->SetPixelV(p.x   -   lXoffset,   p.y   +   lYoffset,   crColour);   
			pDC->SetPixelV(p.x   -   lXoffset,   p.y   -   lYoffset,   crColour);   
		}   
		
		//Advance   the   error   term   and   the   constant   X   axis   step   
		lError   +=   lYoffset++;   
		
		//Check   to   see   if   error   term   has   overflowed   
		if   ((lError   +=   lYoffset)   >=   0)   
			lError   -=   --lXoffset   *   2;   
		
		if   (bDashed   &&   (++nDash   ==   nDashLength))   {   
			nDash   =   0;   
			bDashOn   =   !bDashOn;   
		}   
		
	}   while   (lYoffset   <=   lXoffset); //Continue   until   halfway   point   
}     

void   DrawCircle(CDC*   pDC,   CPoint   p,   LONG   lRadius,   COLORREF   crBright,   COLORREF   crDark)   
{   
	LONG   lError,   lXoffset,   lYoffset;   
    
	//Check   to   see   that   the   coordinates   are   valid   
	ASSERT(   (p.x   +   lRadius   <=   LONG_MAX)   &&   (p.y   +   lRadius   <=   LONG_MAX)   );   
	ASSERT(   (p.x   -   lRadius   >=   LONG_MIN)   &&   (p.y   -   lRadius   >=   LONG_MIN)   );   
    
	//Set   starting   values   
	lXoffset   =   lRadius;   
	lYoffset   =   0;   
	lError       =   -lRadius;   
    
	do   {   
		const   double   Pi   =   3.141592654,     
			Pi_on_2   =   Pi   *   0.5,   
			Three_Pi_on_2   =   Pi   *   1.5;   
		COLORREF   crColour;   
		double       dAngle   =   atan2(lYoffset,   lXoffset);   
		
		//Draw   the   current   pixel,   reflected   across   all   eight   arcs   
		crColour   =   GetColour(dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   +   lXoffset,   p.y   +   lYoffset,   crColour);   
		
		crColour   =   GetColour(Pi_on_2   -   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   +   lYoffset,   p.y   +   lXoffset,   crColour);   
		
		crColour   =   GetColour(Pi_on_2   +   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   -   lYoffset,   p.y   +   lXoffset,   crColour);   
		
		crColour   =   GetColour(Pi   -   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   -   lXoffset,   p.y   +   lYoffset,   crColour);   
		
		crColour   =   GetColour(-Pi   +   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   -   lXoffset,   p.y   -   lYoffset,   crColour);   
		
		crColour   =   GetColour(-Pi_on_2   -   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   -   lYoffset,   p.y   -   lXoffset,   crColour);   
		
		crColour   =   GetColour(-Pi_on_2   +   dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   +   lYoffset,   p.y   -   lXoffset,   crColour);   
		
		crColour   =   GetColour(-dAngle,   crBright,   crDark);   
		pDC->SetPixelV(p.x   +   lXoffset,   p.y   -   lYoffset,   crColour);   
		
		//Advance   the   error   term   and   the   constant   X   axis   step   
		lError   +=   lYoffset++;   
		
		//Check   to   see   if   error   term   has   overflowed   
		if   ((lError   +=   lYoffset)   >=   0)   
			lError   -=   --lXoffset   *   2;   
		
	}   while   (lYoffset   <=   lXoffset); //Continue   until   halfway   point   
}     


/////////////////////////////////////////////////////////////////////////////   
//   CRoundButton   

CRoundButton::CRoundButton()   
{   
	m_bDrawDashedFocusCircle   =   TRUE;   
}   

CRoundButton::~CRoundButton()   
{   
	m_rgn.DeleteObject();   
}   

BEGIN_MESSAGE_MAP(CRoundButton,   CButton)   
//{{AFX_MSG_MAP(CRoundButton)   
//}}AFX_MSG_MAP   
END_MESSAGE_MAP()   

/////////////////////////////////////////////////////////////////////////////   
//   CRoundButton   message   handlers   

void   CRoundButton::PreSubclassWindow()     
{   
	CButton::PreSubclassWindow();   
    
	ModifyStyle(0,   BS_OWNERDRAW);   
    
	CRect   rect;   
	GetClientRect(rect);   
    
	//   Resize   the   window   to   make   it   square   
	rect.bottom   =   rect.right   =   min(rect.bottom,rect.right);   
    
	//   Get   the   vital   statistics   of   the   window   
	m_ptCentre   =   rect.CenterPoint();   
	m_nRadius     =   rect.bottom/2-1;   
    
	//   Set   the   window   region   so   mouse   clicks   only   activate   the   round   section     
	//   of   the   button   
	m_rgn.DeleteObject();     
	SetWindowRgn(NULL,   FALSE);   
	m_rgn.CreateEllipticRgnIndirect(rect);   
	SetWindowRgn(m_rgn,   TRUE);   
    
	//   Convert   client   coords   to   the   parents   client   coords   
	ClientToScreen(rect);   
	CWnd*   pParent   =   GetParent();   
	if   (pParent)   pParent->ScreenToClient(rect);   
    
	//   Resize   the   window   
	MoveWindow(rect.left,   rect.top,   rect.Width(),   rect.Height(),   TRUE);   
}   

void   CRoundButton::DrawItem(LPDRAWITEMSTRUCT   lpDrawItemStruct)     
{   
	ASSERT(lpDrawItemStruct   !=   NULL);   
    
	CDC*   pDC       =   CDC::FromHandle(lpDrawItemStruct->hDC);   
	CRect   rect   =   lpDrawItemStruct->rcItem;   
	UINT   state   =   lpDrawItemStruct->itemState;   
	UINT   nStyle   =   GetStyle();   
	int   nRadius   =   m_nRadius;   
    
	int   nSavedDC   =   pDC->SaveDC();   
    
	pDC->SelectStockObject(NULL_BRUSH);   
	pDC->FillSolidRect(rect,   ::GetSysColor(COLOR_BTNFACE));   
    
	//   Draw   the   focus   circle   around   the   button   
	if   ((state   &   ODS_FOCUS)   &&   m_bDrawDashedFocusCircle)   
		DrawCircle(pDC,   m_ptCentre,   nRadius--,   RGB(0,0,0));   
    
	//   Draw   the   raised/sunken   edges   of   the   button   (unless   flat)   
	if   (nStyle   &   BS_FLAT)   {   
		DrawCircle(pDC,   m_ptCentre,   nRadius--,   RGB(0,0,0));   
		DrawCircle(pDC,   m_ptCentre,   nRadius--,   ::GetSysColor(COLOR_3DHIGHLIGHT));   
	}   else   {   
		if   ((state   &   ODS_SELECTED)) {   
			DrawCircle(pDC,   m_ptCentre,   nRadius--,     
				::GetSysColor(COLOR_3DDKSHADOW),   ::GetSysColor(COLOR_3DHIGHLIGHT));   
			DrawCircle(pDC,   m_ptCentre,   nRadius--,     
				::GetSysColor(COLOR_3DSHADOW),   ::GetSysColor(COLOR_3DLIGHT));   
		}   else   {   
			DrawCircle(pDC,   m_ptCentre,   nRadius--,     
				::GetSysColor(COLOR_3DHIGHLIGHT),   ::GetSysColor(COLOR_3DDKSHADOW));   
			DrawCircle(pDC,   m_ptCentre,   nRadius--,     
				::GetSysColor(COLOR_3DLIGHT),   ::GetSysColor(COLOR_3DSHADOW));   
		}   
	}   
    
	//   draw   the   text   if   there   is   any   
	CString   strText;   
	GetWindowText(strText);   
    
	if   (!strText.IsEmpty())   
	{   
		CRgn   rgn;   
		rgn.CreateEllipticRgn(m_ptCentre.x-nRadius,   m_ptCentre.y-nRadius,     
			m_ptCentre.x+nRadius,   m_ptCentre.y+nRadius);   
		pDC->SelectClipRgn(&rgn);   
		
		CSize   Extent   =   pDC->GetTextExtent(strText);   
		CPoint   pt   =   CPoint(   m_ptCentre.x   -   Extent.cx/2,   m_ptCentre.x   -   Extent.cy/2   );   
		
		if   (state   &   ODS_SELECTED)   pt.Offset(1,1);   
		
		pDC->SetBkMode(TRANSPARENT);   
		
		if   (state   &   ODS_DISABLED)   
			pDC->DrawState(pt,   Extent,   strText,   DSS_DISABLED,   TRUE,   0,   (HBRUSH)NULL);   
		else   
			pDC->TextOut(pt.x,   pt.y,   strText);   
		
		pDC->SelectClipRgn(NULL);   
		rgn.DeleteObject();   
	}   
    
	//   Draw   the   focus   circle   on   the   inside   of   the   button   
	if   ((state   &   ODS_FOCUS)   &&   m_bDrawDashedFocusCircle)   
		DrawCircle(pDC,   m_ptCentre,   nRadius-2,   RGB(0,0,0),   TRUE);   
    
	pDC->RestoreDC(nSavedDC);   
}   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -