// EightBall2Ctl.cpp : Implementation of the CEightBall2Ctrl ActiveX Control class.

#include "stdafx.h"
#include "EightBall2.h"
#include "EightBall2Ctl.h"
#include "EightBall2Ppg.h"

#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define PI 3.14159265358979323846
#define R2D 180./PI;
#define D2R PI/180.;

IMPLEMENT_DYNCREATE(CEightBall2Ctrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CEightBall2Ctrl, COleControl)
	//{{AFX_MSG_MAP(CEightBall2Ctrl)
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CEightBall2Ctrl, COleControl)
	//{{AFX_DISPATCH_MAP(CEightBall2Ctrl)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "CircleShape", m_circleShape, OnCircleShapeChanged, VT_BOOL)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "GroundColor", m_groundColor, OnGroundColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "SkyColor", m_skyColor, OnSkyColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "HorizonColor", m_horizonColor, OnHorizonColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "OuterRingColor", m_outerRingColor, OnOuterRingColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "OuterRingWidth", m_outerRingWidth, OnOuterRingWidthChanged, VT_I2)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "ReferenceMarkColor", m_referenceMarkColor, OnReferenceMarkColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "GridColor", m_gridColor, OnGridColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MajorGridWidth", m_majorGridWidth, OnMajorGridWidthChanged, VT_I2)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MinorGridWidth", m_minorGridWidth, OnMinorGridWidthChanged, VT_I2)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MaxRollAngle", m_maxRollAngle, OnMaxRollAngleChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MajorRollGridIncrement", m_majorRollGridIncrement, OnMajorRollGridIncrementChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MinorRollGridIncrement", m_minorRollGridIncrement, OnMinorRollGridIncrementChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MajorPitchGridIncrement", m_majorPitchGridIncrement, OnMajorPitchGridIncrementChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MinorPitchGridIncrement", m_minorPitchGridIncrement, OnMinorPitchGridIncrementChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MaxPitchAngle", m_maxPitchAngle, OnMaxPitchAngleChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CEightBall2Ctrl, "MaxPitchGridAngle", m_maxPitchGridAngle, OnMaxPitchGridAngleChanged, VT_R8)
	DISP_PROPERTY_EX(CEightBall2Ctrl, "Roll", GetRoll, SetRoll, VT_R8)
	DISP_PROPERTY_EX(CEightBall2Ctrl, "Pitch", GetPitch, SetPitch, VT_R8)
	DISP_STOCKPROP_BACKCOLOR()
	DISP_STOCKPROP_CAPTION()
	DISP_STOCKPROP_FONT()
	DISP_STOCKPROP_FORECOLOR()
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CEightBall2Ctrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CEightBall2Ctrl, COleControl)
	//{{AFX_EVENT_MAP(CEightBall2Ctrl)
	// NOTE - ClassWizard will add and remove event map entries
	//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CEightBall2Ctrl, 3)
	PROPPAGEID(CEightBall2PropPage::guid)
	PROPPAGEID(CLSID_CColorPropPage)
	PROPPAGEID(CLSID_CFontPropPage)
END_PROPPAGEIDS(CEightBall2Ctrl)


/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CEightBall2Ctrl, "EIGHTBALL2.EightBall2Ctrl.1",
	0xe5c17c41, 0x1f7c, 0x4c3f, 0x89, 0x34, 0xeb, 0xca, 0xfc, 0xce, 0x91, 0xb1)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CEightBall2Ctrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DEightBall2 =
		{ 0xd8002d5b, 0x94c2, 0x45e7, { 0x8a, 0x4c, 0x66, 0xad, 0x2, 0xea, 0xbb, 0xd4 } };
const IID BASED_CODE IID_DEightBall2Events =
		{ 0x924bc82c, 0x8ee1, 0x4b5b, { 0x98, 0xdc, 0xad, 0xcb, 0x3c, 0xa1, 0x15, 0x8d } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwEightBall2OleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CEightBall2Ctrl, IDS_EIGHTBALL2, _dwEightBall2OleMisc)


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::CEightBall2CtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CEightBall2Ctrl

BOOL CEightBall2Ctrl::CEightBall2CtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegApartmentThreading to 0.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_EIGHTBALL2,
			IDB_EIGHTBALL2,
			afxRegApartmentThreading,
			_dwEightBall2OleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::CEightBall2Ctrl - Constructor

CEightBall2Ctrl::CEightBall2Ctrl()
{
	InitializeIIDs(&IID_DEightBall2, &IID_DEightBall2Events);

	// TODO: Initialize your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::~CEightBall2Ctrl - Destructor

CEightBall2Ctrl::~CEightBall2Ctrl()
{
	// TODO: Cleanup your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::OnDraw - Drawing function

void CEightBall2Ctrl::OnDraw(CDC* pdc, const CRect& rcBounds,
							 const CRect& rcInvalid)
{
    // Create a compatible DC.
    HDC hdcMem = CreateCompatibleDC(pdc->GetSafeHdc());

    // Create a bitmap big enough for client rectangle.
    HBITMAP hbmMem = CreateCompatibleBitmap(pdc->GetSafeHdc(),
		rcBounds.right-rcBounds.left, rcBounds.bottom-rcBounds.top);

    // Select the bitmap into the off-screen DC.
    HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, hbmMem);

    // Render the image into the offscreen DC.
	CDC *pdcm = CDC::FromHandle(hdcMem);
	MyOnDraw(pdcm,rcBounds,rcInvalid);

    // Blt the changes to the screen DC.
    BitBlt(pdc->GetSafeHdc(),rcBounds.left, rcBounds.top,
           rcBounds.right-rcBounds.left, rcBounds.bottom-rcBounds.top,
           hdcMem, 0, 0, SRCCOPY);

    // Done with off-screen bitmap and DC.
    SelectObject(hdcMem, hbmOld);
    DeleteObject(hbmMem);
    DeleteDC(hdcMem);
}

void CEightBall2Ctrl::MyOnDraw(CDC* pdc, const CRect& rcBounds,
							 const CRect& rcInvalid)
{
    CBrush* pOldBrush;
    CBrush bkBrush(TranslateColor(GetBackColor()));
    CPen* pOldPen;
    CRect rc = rcBounds;
	POINT p1,p2,p3,p4,p5;
	CPoint points[3];
	CFont* pOldFont;
    TEXTMETRIC tm;
	char label[32];
    const CString& strCaption = InternalGetText();

    // Set the ForeColor property color and transparent background mode into the device context
    pdc->SetTextColor(TranslateColor(GetForeColor()));
    pdc->SetBkMode(TRANSPARENT);

    // Paint the background using the BackColor property
    pdc->FillRect(rcBounds, &bkBrush);

    // Get the coordinates
    GetDrawRect(&rc);
	GetChordEndpoints(&rc,&p1,&p2);

	// Draw the ellipse
	CBrush ellipseBrush(m_skyColor);
	pOldBrush = pdc->SelectObject(&ellipseBrush);
	CPen ellipseStroke;
	ellipseStroke.CreatePen(PS_SOLID, m_outerRingWidth, m_outerRingColor);
	pOldPen = pdc->SelectObject( &ellipseStroke );
	pdc->Ellipse(rc);

	// Draw the chord
	CBrush chordBrush(m_groundColor);
	pdc->SelectObject(&chordBrush);
	CPen chordStroke;
	chordStroke.CreatePen(PS_SOLID, m_outerRingWidth, m_horizonColor);
	pdc->SelectObject( &chordStroke );
	pdc->Chord(rc,p1,p2);

	// Draw the outer ring
	pdc->SelectStockObject(NULL_BRUSH);
	CPen outerStroke;
	outerStroke.CreatePen(PS_SOLID, m_outerRingWidth, m_outerRingColor);
	pdc->SelectObject( &outerStroke );
	pdc->Ellipse(rc);

	// Set the font
	pOldFont = SelectStockFont(pdc);
    pdc->GetTextMetrics(&tm);

	// Make the major grid pen
	CPen majorGridStroke;
	majorGridStroke.CreatePen(PS_SOLID, m_majorGridWidth, m_gridColor);

	// Draw the major roll grid
	pdc->SetTextAlign(TA_CENTER | TA_TOP);
	pdc->SelectObject(&majorGridStroke);
	int nTicks = MyRound(2.*m_maxRollAngle/m_majorRollGridIncrement)+1;
	for (int tick=0; tick < nTicks; tick++)
	{
		double angle = -m_maxRollAngle + tick*m_majorRollGridIncrement;
		GetRollGridEndpoints(&rc,&p1,&p2,angle-m_roll,0.8);
		pdc->MoveTo(p1);
		pdc->LineTo(p2);
		sprintf(label,"%d",MyRound(angle)); 
		pdc->ExtTextOut(p1.x,p1.y,ETO_CLIPPED, rc, label,
			strlen(label), NULL);		
	}

	// Make the minor grid pen
	CPen minorGridStroke;
	minorGridStroke.CreatePen(PS_SOLID, m_minorGridWidth, m_gridColor);
	
	// Draw the minor roll grid
	pdc->SelectObject(&minorGridStroke);
	nTicks = MyRound(2.*m_maxRollAngle/m_minorRollGridIncrement)+1;
	for (tick=0; tick < nTicks; tick++)
	{
		double angle = -m_maxRollAngle + tick*m_minorRollGridIncrement;
		GetRollGridEndpoints(&rc,&p1,&p2,angle-m_roll,0.9);
		pdc->MoveTo(p1);
		pdc->LineTo(p2);	
	}

	// Draw the major pitch grid
	pdc->SelectObject(&majorGridStroke);
	nTicks = MyRound(2.*m_maxPitchGridAngle/m_majorPitchGridIncrement)+1;
	for (tick=0; tick < nTicks && fabs(m_pitch) < m_maxPitchGridAngle; tick++)
	{
		double angle = -m_maxPitchGridAngle + tick*m_majorPitchGridIncrement;
		GetPitchGridEndpoints(&rc,&p1,&p2,angle-m_pitch,0.3);
		pdc->MoveTo(p1);
		pdc->LineTo(p2);
		if (fabs(angle+m_pitch) > 1e-9) {
			sprintf(label,"%d",MyRound(angle)); 
			pdc->SetTextAlign(TA_RIGHT);
			pdc->ExtTextOut(p1.x,p1.y-tm.tmHeight/2,ETO_CLIPPED, rc, label,
				strlen(label), NULL);
			pdc->SetTextAlign(TA_LEFT);
			pdc->ExtTextOut(p2.x,p2.y-tm.tmHeight/2,ETO_CLIPPED, rc, label,
				strlen(label), NULL);	
		}	
	}

	// Draw the minor pitch grid
	pdc->SelectObject(&minorGridStroke);
	nTicks = MyRound(2.*m_maxPitchGridAngle/m_minorPitchGridIncrement)+1;
	for (tick=0; tick < nTicks && fabs(m_pitch) < m_maxPitchGridAngle; tick++)
	{
		double angle = -m_maxPitchGridAngle + tick*m_minorPitchGridIncrement;
		GetPitchGridEndpoints(&rc,&p1,&p2,angle-m_pitch,0.25);
		pdc->MoveTo(p1);
		pdc->LineTo(p2);	
	}

	// Draw the horizon reference
	CPen referenceStroke;
	referenceStroke.CreatePen(PS_SOLID, m_outerRingWidth, m_referenceMarkColor);
	pdc->SelectObject( &referenceStroke );	
	GetReferenceMarks(&rc,&p1,&p2,&p3,&p4,&p5);
	pdc->MoveTo(p1);
	pdc->LineTo(p2);
	pdc->MoveTo(p3);
	pdc->LineTo(p3);
	pdc->MoveTo(p4);
	pdc->LineTo(p5);

	// Draw the roll reference
	pdc->SelectStockObject(NULL_PEN);
	CBrush referenceBrush(m_referenceMarkColor);
	pdc->SelectObject(&referenceBrush);
	GetReferencePointer(&rc,points);
	pdc->Polygon(points,3);

    // Draw the caption using the stock Font and ForeColor properties
	pdc->SetTextAlign(TA_CENTER | TA_TOP);
    pdc->ExtTextOut((rc.left + rc.right) / 2,rc.bottom - 2*tm.tmHeight,
        ETO_CLIPPED, rc, strCaption, strCaption.GetLength(), NULL);

	// Restore the device to its original state
    pdc->SelectObject(pOldPen);
    pdc->SelectObject(pOldBrush);
	pdc->SelectObject(pOldFont);
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::DoPropExchange - Persistence support

void CEightBall2Ctrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	
	PX_Bool(pPX, _T("CircleShape"), m_circleShape, TRUE);
	PX_Double(pPX, _T("Roll"), m_roll, 0.);
	PX_Double(pPX, _T("Pitch"), m_pitch, 0.);
	PX_Color(pPX, _T("GroundColor"), m_groundColor, RGB(0,0,255));
	PX_Color(pPX, _T("SkyColor"), m_skyColor, RGB(0,255,0));
	PX_Color(pPX, _T("HorizonColor"), m_horizonColor, RGB(255,255,255));
	PX_Color(pPX, _T("OuterRingColor"), m_outerRingColor, RGB(0,0,0));
	PX_Color(pPX, _T("GridColor"), m_gridColor, RGB(255,255,255));
	PX_Color(pPX, _T("ReferenceMarkColor"), m_referenceMarkColor, RGB(255,0,0));
	PX_Double(pPX, _T("MaxRollAngle"), m_maxRollAngle, 60.);
	PX_Double(pPX, _T("MaxPitchAngle"), m_maxPitchAngle, 45.);
	PX_Double(pPX, _T("MaxPitchGridAngle"), m_maxPitchGridAngle, 20.);
	PX_Double(pPX, _T("MajorRollGridIncrement"), m_majorRollGridIncrement, 30.);
	PX_Double(pPX, _T("MinorRollGridIncrement"), m_minorRollGridIncrement, 5.);
	PX_Double(pPX, _T("MajorPitchGridIncrement"), m_majorPitchGridIncrement, 10.);
	PX_Double(pPX, _T("MinorPitchGridIncrement"), m_minorPitchGridIncrement, 5.);
	PX_Short(pPX, _T("OuterRingWidth"), m_outerRingWidth, 3);
	PX_Short(pPX, _T("MajorGridWidth"), m_majorGridWidth, 2);
	PX_Short(pPX, _T("MinorGridWidth"), m_minorGridWidth, 1);
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::GetControlFlags -
// Flags to customize MFC's implementation of ActiveX controls.
//
// For information on using these flags, please see MFC technical note
// #nnn, "Optimizing an ActiveX Control".
DWORD CEightBall2Ctrl::GetControlFlags()
{
	DWORD dwFlags = COleControl::GetControlFlags();


	// The control will not be redrawn when making the transition
	// between the active and inactivate state.
	dwFlags |= noFlickerActivate;
	return dwFlags;
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::OnResetState - Reset control to default state

void CEightBall2Ctrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl::AboutBox - Display an "About" box to the user

void CEightBall2Ctrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_EIGHTBALL2);
	dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CEightBall2Ctrl message handlers
double CEightBall2Ctrl::GetRoll() 
{
	return m_roll;
}

void CEightBall2Ctrl::SetRoll(double newValue) 
{
	m_roll = newValue;
	if (m_roll > m_maxRollAngle) m_roll = m_maxRollAngle;
	else if (m_roll < -m_maxRollAngle) m_roll = -m_maxRollAngle;

    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

double CEightBall2Ctrl::GetPitch() 
{
	return m_pitch;
}

void CEightBall2Ctrl::SetPitch(double newValue) 
{
	m_pitch = newValue;
	if (m_pitch > m_maxPitchAngle) m_pitch = m_maxPitchAngle;
	else if (m_pitch < -m_maxPitchAngle) m_pitch = -m_maxPitchAngle;

	// force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::GetDrawRect(CRect *rc)
{
    if (m_circleShape)
    {
        int cx = rc->right - rc->left;
        int cy = rc->bottom - rc->top;

        if (cx > cy) {
            rc->left += (cx - cy) / 2;
            rc->right = rc->left + cy;
			rc->top += m_outerRingWidth/2;
			rc->bottom -= m_outerRingWidth/2;
        } else {
            rc->top += (cy - cx) / 2;
            rc->bottom = rc->top + cx;
			rc->left += m_outerRingWidth/2;
			rc->right -= m_outerRingWidth/2;
        }
    }
}

void CEightBall2Ctrl::GetRollGridEndpoints(CRect *rc,POINT *p1,POINT *p2,
										   double angle, double startRange)
{
	POINT center;
	GetCenter(rc,&center);
	double radius = GetRadius(rc);
	Reckon(radius*startRange,angle,&center,p1);
	Reckon(radius*(1.-startRange),angle,p1,p2);
}

void CEightBall2Ctrl::GetPitchGridEndpoints(CRect *rc,POINT *p1,POINT *p2,
										   double angle, double startRange)
{
	POINT center, lineCenter;
	GetCenter(rc,&center);
	double radius = GetRadius(rc);
	Reckon(radius*angle/m_maxPitchAngle,-m_roll,&center,&lineCenter);
	Reckon(radius*startRange,-m_roll-90.,&lineCenter,p1);
	Reckon(radius*startRange,-m_roll+90.,&lineCenter,p2);
}

// Expects azimuth in compass degrees
void CEightBall2Ctrl::Reckon(double range, double azimuth,
							 POINT *p1, POINT *p2)
{
	double radians = PI/2. - azimuth*D2R;
	p2->x = MyRound((double)p1->x + range*cos(radians));
	p2->y = MyRound((double)p1->y - range*sin(radians));
}

void CEightBall2Ctrl::GetCenter(CRect *rc, POINT *p)
{
	p->x = MyRound((double)rc->left + (double) (rc->right - rc->left)/2.);
    p->y = MyRound((double)rc->top + (double) (rc->bottom - rc->top)/2.);
}

double CEightBall2Ctrl::GetRadius(CRect *rc)
{
	double cx = (double) (rc->right - rc->left);
    double cy = (double) (rc->bottom - rc->top);
	return cx < cy ? cx/2. : cy/2.;
}

void CEightBall2Ctrl::GetChordEndpoints(CRect *rc, POINT *p1, POINT *p2)
{
	POINT center, lineCenter;
	GetCenter(rc,&center);
	double radius = GetRadius(rc);
	Reckon(-radius*m_pitch/m_maxPitchAngle,-m_roll,&center,&lineCenter);
	Reckon(radius,-m_roll-90.,&lineCenter,p1);
	Reckon(radius,-m_roll+90.,&lineCenter,p2);
}

void CEightBall2Ctrl::GetReferenceMarks(CRect *rc,POINT *p1,POINT *p2,
										POINT *p3,POINT *p4,POINT *p5)
{
	double cx = (double) (rc->right - rc->left);
	double cy = (double) (rc->bottom - rc->top);
	long my = rc->top + MyRound(cy/2.);
	p1->x = rc->left + MyRound(cx/4.);
	p1->y = my;
	p2->x = rc->left + MyRound(cx*5./12.);
	p2->y = my;
	p3->x = rc->left + MyRound(cx/2.);
	p3->y = my;
	p4->x = rc->left + MyRound(cx*7./12.);
	p4->y = my;
	p5->x = rc->left + MyRound(cx*3./4.);
	p5->y = my;
}

void CEightBall2Ctrl::GetReferencePointer(CRect *rc,CPoint points[])
{
	double cx = (double) (rc->right - rc->left);
	points[0].x = rc->left + MyRound(cx/2.) - m_outerRingWidth;
	points[0].y = rc->top; 
	points[1].x = rc->left + MyRound(cx/2.) + m_outerRingWidth;
	points[1].y = rc->top;
	points[2].x = rc->left + MyRound(cx/2.);
	points[2].y = rc->top + 2*m_outerRingWidth;
}

long int CEightBall2Ctrl::MyRound(double num_in)
{
	double temp;
	if ( num_in < 0 ) {
		temp = num_in - ceil(num_in);
		if(temp > -0.500000)
			return (long int)floor(num_in);
		else
			return (long int)ceil(num_in);
	} else {
		temp = num_in - floor(num_in);
		if(temp > 0.500000)
			return (long int)ceil(num_in);
		else
			return (long int)floor(num_in);
	}
}

BOOL CEightBall2Ctrl::OnEraseBkgnd(CDC* pDC) 
{	
	//return COleControl::OnEraseBkgnd(pDC);
	return (LRESULT)1;
}

void CEightBall2Ctrl::OnCircleShapeChanged() 
{
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnGroundColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnSkyColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnHorizonColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnOuterRingColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnOuterRingWidthChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnReferenceMarkColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnGridColorChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMajorGridWidthChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMinorGridWidthChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMaxRollAngleChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMajorRollGridIncrementChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMinorRollGridIncrementChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMajorPitchGridIncrementChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMinorPitchGridIncrementChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMaxPitchAngleChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}

void CEightBall2Ctrl::OnMaxPitchGridAngleChanged() 
{
	// TODO: Add notification handler code
    // force the control to redraw itself
    InvalidateControl();
	SetModifiedFlag();
}
