📄 spherebutton.cpp
字号:
// BounceButton.cpp : implementation file
//
#include "stdafx.h"
#include "SphereButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DEFAULT_MARGIN 20
/////////////////////////////////////////////////////////////////////////////
// CSphereButton
CSphereButton::CSphereButton( bool bDepressed, bool bCenterAlign )
{
m_bDepressed = bDepressed;
m_bCenterAlign = bCenterAlign;
m_bDrawFocusRect = false;
m_bMouseTracking = false;
m_bLMouseButtonDown = false;
m_bMouseTracking = false;
m_nMargin = DEFAULT_MARGIN;
}
CSphereButton::~CSphereButton()
{
m_btnRgn.DeleteObject();
m_BoldFont.DeleteObject();
}
BEGIN_MESSAGE_MAP(CSphereButton, CButton)
//{{AFX_MSG_MAP(CSphereButton)
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSphereButton message handlers
void CSphereButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);
CRect rect;
GetClientRect(rect);
LOGFONT lf;
GetFont()->GetLogFont(&lf);
m_nRadius = lf.lfHeight;
if( m_nRadius == 0 )
m_nRadius = 15;
if( m_nRadius < 0 )
m_nRadius = (-1)*m_nRadius;
m_nRadius = (int)(rect.bottom*0.5)-5;
if( m_nRadius > 6 )
m_nRadius = 6;
m_ptCenter.x = rect.left+m_nRadius+1;
if( m_bCenterAlign )
{
m_ptCenter.y = rect.top+(int)(rect.Height()*0.5);
}
else
{
m_ptCenter.y = rect.top+m_nRadius+1;
}
m_btnRgn.CreateEllipticRgn( rect.left, m_ptCenter.y-m_nRadius-1, rect.left+(2*m_nRadius)+4, m_ptCenter.y+m_nRadius+3 );
LOGFONT logfont;
CFont* pWndFont = GetFont();
pWndFont->GetLogFont( &logfont );
logfont.lfWeight = 700;
m_BoldFont.CreateFontIndirect( &logfont );
}
void CSphereButton::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( lpDrawItemStruct->itemState & ODS_DISABLED )
{
DrawCircle(pDC, m_ptCenter, nRadius+1, ::GetSysColor(COLOR_BTNHIGHLIGHT));
nRadius-=4;
}
else
{
DrawCircle(pDC, m_ptCenter, nRadius+1, ::GetSysColor(COLOR_WINDOWFRAME));
if (nStyle & BS_FLAT)
{
DrawCircle(pDC, m_ptCenter, nRadius--, RGB(0,0,0));
DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DHIGHLIGHT));
}
else
{
if (m_bDepressed)
{
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT));
pDC->SelectObject( m_BoldFont );
}
else
{
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(pDC, m_ptCenter, nRadius--,
::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
}
}
}
CString strText;
GetWindowText(strText);
CSize Extent;
CPoint pt;
CRect textRect, clientRect;
GetClientRect( clientRect );
textRect = clientRect;
textRect.left += (2*(m_nRadius+5));
textRect.right -= 2;
if (!strText.IsEmpty())
{
Extent = pDC->GetTextExtent(strText);
pt.x = rect.left + (2*nRadius) + m_nMargin;
pt.y = (int)((rect.Height() - Extent.cy)*0.5);
pDC->SetBkMode(TRANSPARENT);
if (state & ODS_DISABLED)
pDC->DrawState(pt, Extent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
else
{
pDC->DrawText( strText, textRect, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_CALCRECT );
int h = textRect.Height();
textRect.top = clientRect.top+(int)((clientRect.Height()-textRect.Height())*0.5);
textRect.bottom = textRect.top + h;
pDC->DrawText( strText, textRect, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK );
m_textRect = textRect;
}
}
textRect.right += 2;
POINT point;
GetCursorPos( &point );
if (m_bDrawFocusRect )
{
textRect.InflateRect(1,1);
textRect.right++;
pDC->DrawFocusRect( textRect );
m_textRect = textRect;
}
pDC->RestoreDC(nSavedDC);
}
void CSphereButton::OnKillFocus(CWnd*)
{
if( m_bDrawFocusRect )
{
m_bDrawFocusRect = false;
Invalidate();
}
}
void CSphereButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
POINT pt;
if( m_bDrawFocusRect )
{
::GetCursorPos(&pt);
::MapWindowPoints(NULL,(HWND)(m_hWnd),&pt,1);
::SendMessage((HWND)(m_hWnd),WM_LBUTTONDOWN,0,MAKELPARAM(pt.x,pt.y));
CButton::OnLButtonDblClk(nFlags, point);
}
}
void CSphereButton::OnLButtonUp(UINT nFlags, CPoint point)
{
if( m_bDrawFocusRect )
{
if( m_bLMouseButtonDown )
m_bLMouseButtonDown = false;
CButton::OnLButtonUp(nFlags, point);
}
}
void CSphereButton::OnLButtonDown(UINT nFlags, CPoint point)
{
POINT pt;
pt.x = point.x;
pt.y = point.y;
if( m_bDrawFocusRect )
{
m_bLMouseButtonDown = true;
m_bDepressed = !m_bDepressed;
SetFocus();
Invalidate();
CButton::OnLButtonDown(nFlags, point);
}
}
void CSphereButton::Set_Check(int nCheck)
{
switch( nCheck )
{
case 0 : { if( m_bDepressed )
{
m_bDepressed = false;
Invalidate();
}
break;
}
case 1 : { if( !m_bDepressed )
{
m_bDepressed = true;
Invalidate();
}
break;
}
case 2 : {
EnableWindow(false);
break;
}
default: break;
}
}
void CSphereButton::OnMouseMove(UINT, CPoint)
{
if( !m_bMouseTracking || GetCapture()!=this )
{
OnMouseEnter();
}
else
{
if( !MouseOverItem() )
OnMouseLeave();
}
if( MouseOverItem() && !m_bDrawFocusRect )
{
m_bDrawFocusRect = true;
Invalidate();
UpdateWindow();
}
if( !MouseOverItem() && m_bDrawFocusRect )
{
m_bDrawFocusRect = false;
Invalidate();
UpdateWindow();
}
}
bool CSphereButton::MouseOverItem()
{
POINT mouse;
GetCursorPos( &mouse );
ScreenToClient( &mouse );
return( (m_textRect.PtInRect( mouse )) || (m_btnRgn.PtInRegion( mouse )) );
}
void CSphereButton::OnMouseEnter(void)
{
m_bMouseTracking = TRUE;
m_bLMouseButtonDown = false;
GetFocus();
SetCapture();
}
void CSphereButton::OnMouseLeave(void)
{
m_bMouseTracking = false;
bool RedrawNeeded = false;
ReleaseCapture();
if( m_bLMouseButtonDown )
{
m_bDepressed = !m_bDepressed;
m_bLMouseButtonDown = false;
RedrawNeeded = true;
}
if( m_bDrawFocusRect )
{
m_bDrawFocusRect = false;
RedrawNeeded = true;
}
if( RedrawNeeded )
{
Invalidate();
UpdateWindow();
}
}
bool CSphereButton::IsDepressed()
{
return m_bDepressed;
}
bool CSphereButton::Depress(bool bDown)
{
if( bDown != m_bDepressed )
{
m_bDepressed = bDown;
Invalidate();
return !m_bDepressed;
}
return m_bDepressed;
}
COLORREF CSphereButton::GetColor(double dAngle, COLORREF crBright, COLORREF crDark)
{
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 CSphereButton::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) );
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);
}
lError += lYoffset++;
if ((lError += lYoffset) >= 0)
lError -= --lXoffset * 2;
if (bDashed && (++nDash == nDashLength)) {
nDash = 0;
bDashOn = !bDashOn;
}
} while (lYoffset <= lXoffset); //Continue until halfway point
}
void CSphereButton::DrawCircle(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);
crColour = GetColor(dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lXoffset, p.y + lYoffset, crColour);
crColour = GetColor(Pi_on_2 - dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lYoffset, p.y + lXoffset, crColour);
crColour = GetColor(Pi_on_2 + dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lYoffset, p.y + lXoffset, crColour);
crColour = GetColor(Pi - dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lXoffset, p.y + lYoffset, crColour);
crColour = GetColor(-Pi + dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lXoffset, p.y - lYoffset, crColour);
crColour = GetColor(-Pi_on_2 - dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lYoffset, p.y - lXoffset, crColour);
crColour = GetColor(-Pi_on_2 + dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lYoffset, p.y - lXoffset, crColour);
crColour = GetColor(-dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lXoffset, p.y - lYoffset, crColour);
lError += lYoffset++;
if ((lError += lYoffset) >= 0)
lError -= --lXoffset * 2;
} while (lYoffset <= lXoffset);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -