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

📄 ellipsebutton.cpp

📁 mytoolpad 源码
💻 CPP
字号:
#include "stdafx.h"
#include "math.h"
#include "EllipseButton.h"

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



COLORREF CRoundButton::GetColour(double dAngle, COLORREF crBright, COLORREF crDark)
{
#define Rad2Deg	180.0/3.1415 

#define LIGHT_SOURCE_ANGLE	-1.88

	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));

	return RGB(Red, Green, Blue);
}

void CRoundButton::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;

	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 CRoundButton::DrawCircleRight(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 four 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(-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
} 

void CRoundButton::DrawCircleLeft(CDC* pDC, CPoint p, LONG lRadius, COLORREF crBright, COLORREF crDark)
{
	LONG lError, lXoffset, lYoffset;

	ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) );
	ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) );

	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(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);

		//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()
{
	m_bDrawDashedFocusCircle = TRUE;
}

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

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


void CRoundButton::PreSubclassWindow() 
{
	CButton::PreSubclassWindow();

	ModifyStyle(0, BS_OWNERDRAW);

	CRect rect;
	GetClientRect(rect);

	m_bStretch = rect.Width() > rect.Height() ? TRUE : FALSE;
	if(!m_bStretch)
		rect.bottom = rect.right = min(rect.bottom,rect.right);
	m_ptCentre = m_ptLeft = m_ptRight = rect.CenterPoint();
	m_nRadius  = rect.bottom/2-1;
	m_ptLeft.x = m_nRadius;
	m_ptRight.x = rect.right - m_nRadius - 1;

	m_rgn.DeleteObject(); 
	SetWindowRgn(NULL, FALSE);
	m_rgn.CreateEllipticRgnIndirect(rect);
	SetWindowRgn(m_rgn, TRUE);

	ClientToScreen(rect);
	CWnd* pParent = GetParent();
	if (pParent) pParent->ScreenToClient(rect);

	if(!m_bStretch)	
		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));

	if ((state & ODS_FOCUS) && m_bDrawDashedFocusCircle && !m_bStretch)
		DrawCircle(pDC, m_ptCentre, nRadius--, RGB(0,0,0));

	if (nStyle & BS_FLAT) 
	{
		if(m_bStretch)
		{
			CPen* oldpen;
			
			CRect LeftBound(0,0,nRadius*2,nRadius*2);
			CRect RightBound(m_ptRight.x-nRadius,0,m_ptRight.x+nRadius,nRadius*2);

			oldpen = pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)));
			pDC->Arc(LeftBound, CPoint(m_ptLeft.x,0), CPoint(m_ptLeft.x,nRadius*2));
			pDC->Arc(RightBound, CPoint(m_ptRight.x,nRadius*2), CPoint(m_ptRight.x,0));
			pDC->MoveTo(m_ptLeft.x,0); pDC->LineTo(m_ptRight.x,0);
			pDC->MoveTo(m_ptLeft.x,nRadius*2-1); pDC->LineTo(m_ptRight.x,nRadius*2-1);

			nRadius--;
			LeftBound.DeflateRect(1,1);
			RightBound.DeflateRect(1,1);

			delete pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)));
			pDC->Arc(LeftBound, CPoint(m_ptLeft.x,1), CPoint(m_ptLeft.x,nRadius*2));
			pDC->Arc(RightBound, CPoint(m_ptRight.x,nRadius*2), CPoint(m_ptRight.x,0));
			pDC->MoveTo(m_ptLeft.x,1); pDC->LineTo(m_ptRight.x,1);
			pDC->MoveTo(m_ptLeft.x,nRadius*2); pDC->LineTo(m_ptRight.x,nRadius*2);

			delete pDC->SelectObject(oldpen);
		}
		else
		{
			DrawCircle(pDC, m_ptCentre, nRadius--, ::GetSysColor(COLOR_3DDKSHADOW));
			DrawCircle(pDC, m_ptCentre, nRadius--, ::GetSysColor(COLOR_3DHIGHLIGHT));
		}
	} 
	else 
	{
		if ((state & ODS_SELECTED))	
		{
			DrawCircleLeft(pDC, m_ptLeft, nRadius, 
					   ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT));
			DrawCircleRight(pDC, m_ptRight, nRadius, 
					   ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT));
			DrawCircleLeft(pDC, m_ptLeft, nRadius-1, 
					   ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT));
			DrawCircleRight(pDC, m_ptRight, nRadius-1, 
					   ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT));

			if (m_bStretch)
			{
				CPen* oldpen=pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)));
				pDC->MoveTo(m_ptLeft.x, 1); 
				pDC->LineTo(m_ptRight.x, 1);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)));
				pDC->MoveTo(m_ptLeft.x, 2);	
				pDC->LineTo(m_ptRight.x, 2);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DLIGHT)));
				pDC->MoveTo(m_ptLeft.x, m_ptLeft.y + nRadius-1);
				pDC->LineTo(m_ptRight.x, m_ptLeft.y + nRadius-1);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)));
				pDC->MoveTo(m_ptLeft.x, m_ptLeft.y + nRadius);
				pDC->LineTo(m_ptRight.x, m_ptLeft.y + nRadius);

				delete pDC->SelectObject(oldpen);
			}
					   
		} 
		else 
		{
			DrawCircleLeft(pDC, m_ptLeft, nRadius, 
				   ::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
			DrawCircleRight(pDC, m_ptRight, nRadius, 
				   ::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
			DrawCircleLeft(pDC, m_ptLeft, nRadius - 1, 
				   ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
			DrawCircleRight(pDC, m_ptRight, nRadius - 1, 
				   ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));

			if (m_bStretch)
			{
				CPen* oldpen=pDC->SelectObject(new CPen(PS_SOLID, 1, pDC->GetPixel(m_ptLeft.x, 1)));
				pDC->MoveTo(m_ptLeft.x, 1); 
				pDC->LineTo(m_ptRight.x, 1);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, pDC->GetPixel(m_ptLeft.x, 2)));
				pDC->MoveTo(m_ptLeft.x, 2); 
				pDC->LineTo(m_ptRight.x, 2);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, pDC->GetPixel(m_ptLeft.x, m_ptLeft.y + nRadius)));
				pDC->MoveTo(m_ptLeft.x, m_ptLeft.y + nRadius); 
				pDC->LineTo(m_ptRight.x, m_ptLeft.y + nRadius);

				delete pDC->SelectObject(new CPen(PS_SOLID, 1, pDC->GetPixel(m_ptLeft.x, m_ptLeft.y + nRadius - 1)));
				pDC->MoveTo(m_ptLeft.x, m_ptLeft.y + nRadius - 1); 
				pDC->LineTo(m_ptRight.x, m_ptLeft.y + nRadius - 1);
				
				delete pDC->SelectObject(oldpen);
			}
		}
	}
	
	CString strText;
	GetWindowText(strText);

	if (!strText.IsEmpty())
	{
		CRgn rgn;
		if (m_bStretch)
			rgn.CreateRectRgn(m_ptLeft.x-nRadius/2, m_ptCentre.y-nRadius, 
				m_ptRight.x+nRadius/2, m_ptCentre.y+nRadius);
		else
			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.y - 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		//允许状态
		{
			COLORREF oldcol = pDC->SetTextColor(::GetSysColor(COLOR_3DHIGHLIGHT));
//			pDC->TextOut(pt.x, pt.y, strText);
			pDC->SetTextColor(::GetSysColor(COLOR_3DDKSHADOW));
			pDC->TextOut(pt.x-1, pt.y-1, strText);
			pDC->SetTextColor(oldcol);
		}

		pDC->SelectClipRgn(NULL);
		rgn.DeleteObject();
	}

	if ((state & ODS_FOCUS) && m_bDrawDashedFocusCircle && !m_bStretch)
		DrawCircle(pDC, m_ptCentre, nRadius-2, RGB(0,0,0), TRUE);

	pDC->RestoreDC(nSavedDC);
}

⌨️ 快捷键说明

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