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

📄 activeclockctl.cpp

📁 《Visual C++ Bible》或者说是《Visual C++ 宝典》的对应的源码文件
💻 CPP
字号:
// ActiveClockCtl.cpp : Implementation of the CActiveClockCtrl ActiveX Control class.

#include "stdafx.h"
#include "ActiveClock.h"
#include "ActiveClockCtl.h"
#include "ActiveClockPpg.h"

#include <math.h>

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


IMPLEMENT_DYNCREATE(CActiveClockCtrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CActiveClockCtrl, COleControl)
	//{{AFX_MSG_MAP(CActiveClockCtrl)
	ON_WM_CREATE()
	ON_WM_TIMER()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CActiveClockCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CActiveClockCtrl)
	DISP_STOCKPROP_BACKCOLOR()
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CActiveClockCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CActiveClockCtrl, COleControl)
	//{{AFX_EVENT_MAP(CActiveClockCtrl)
	// 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(CActiveClockCtrl, 1)
	PROPPAGEID(CActiveClockPropPage::guid)
END_PROPPAGEIDS(CActiveClockCtrl)


/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CActiveClockCtrl, "ACTIVECLOCK.ActiveClockCtrl.1",
	0x616af326, 0xd5aa, 0x11d0, 0xb7, 0x19, 0, 0xc0, 0xa8, 0x37, 0x35, 0xd8)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CActiveClockCtrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DActiveClock =
		{ 0x616af324, 0xd5aa, 0x11d0, { 0xb7, 0x19, 0, 0xc0, 0xa8, 0x37, 0x35, 0xd8 } };
const IID BASED_CODE IID_DActiveClockEvents =
		{ 0x616af325, 0xd5aa, 0x11d0, { 0xb7, 0x19, 0, 0xc0, 0xa8, 0x37, 0x35, 0xd8 } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwActiveClockOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CActiveClockCtrl, IDS_ACTIVECLOCK, _dwActiveClockOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::CActiveClockCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CActiveClockCtrl

BOOL CActiveClockCtrl::CActiveClockCtrlFactory::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_ACTIVECLOCK,
			IDB_ACTIVECLOCK,
			afxRegApartmentThreading,
			_dwActiveClockOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::CActiveClockCtrl - Constructor

CActiveClockCtrl::CActiveClockCtrl()
{
	InitializeIIDs(&IID_DActiveClock, &IID_DActiveClockEvents);

	m_nClockType = DIGITAL_CLOCK;

}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::~CActiveClockCtrl - Destructor

CActiveClockCtrl::~CActiveClockCtrl()
{
	// TODO: Cleanup your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::OnDraw - Drawing function

void CActiveClockCtrl::OnDraw(CDC* pdc,
const CRect& rcBounds,
const CRect& rcInvalid)
{

	// Fill the control's window rectangle and allow a border
	CBrush brBrush( TranslateColor( GetBackColor() ) );
	pdc->FillRect(rcBounds, &brBrush );

	// Set for transparent drawing mode
	pdc->SetBkMode( TRANSPARENT );

	// Get the current time
	CTime t = CTime::GetCurrentTime();

	// The following block of code draws a digital clock
	if( m_nClockType == DIGITAL_CLOCK ){

		// Since the hour is returned as a value from 0-23,
		// we'll need to adjust it for our customary AM
		// and PM times. The following four variations
		// handle each case.
		char szTime[100];

		// After midnight, before 1 AM
		if( t.GetHour() == 0 )
			wsprintf( szTime, "12:%02d:%02d AM",
				t.GetMinute(),
				t.GetSecond() );

		// After midnight, before noon
		else if( t.GetHour() < 12 )
			wsprintf( szTime, "%02d:%02d:%02d AM",
				t.GetHour(),
				t.GetMinute(),
				t.GetSecond() );

		// Noon, before 1 PM
		else if( t.GetHour() == 12 )
			wsprintf( szTime, "12:%02d:%02d PM",
				t.GetMinute(),
				t.GetSecond() );

		// 1 PM and after
		else
			wsprintf( szTime, "%02d:%02d:%02d PM",
				t.GetHour() - 12,
				t.GetMinute(),
				t.GetSecond() );

		// Get the number of characters in
		// the time string, calculate
		// the average character width (and
		// subract two for good measure),
		// and calculate the average character
		// height.
		int nChars = strlen( szTime );
		int nAvWidth = ( rcBounds.Width() / nChars ) - 3;
		int nAvHeight = rcBounds.Height();

		// Create the font based on the
		// average width and height that
		// we calcuated.
		CFont Font;
		Font.CreateFont( nAvHeight, nAvWidth,
			0, 0, FW_DONTCARE, FALSE, FALSE, 0,
			DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,
			CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
			DEFAULT_PITCH | FF_DONTCARE,
			"Times New Roman" );

		// Select the newly created font into
		// the device context (making sure we
		// save a pointer to the old font.)
		CFont *pOldFont = pdc->SelectObject( &Font );

		// Get the width and height
		// of the text string.
		CSize size = pdc->GetTextExtent( szTime, strlen( szTime ) );

		// Draw the text (centered).
		pdc->TextOut( ( rcBounds.Width() - size.cx ) / 2,
			( rcBounds.Height() - size.cy ) / 2,
			szTime, strlen( szTime ) );

		// Select the old font back into the
		// device context.
		pdc->SelectObject( pOldFont );
		}

	
	// The next block of code draws an analog clock.
	else{

		// Create a small font with which
		// we'll draw the clock digits.
		CFont Font;
		Font.CreateFont( 15, 15,
			0, 0, FW_DONTCARE, FALSE, FALSE, 0,
			DEFAULT_CHARSET, OUT_CHARACTER_PRECIS,
			CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
			DEFAULT_PITCH | FF_DONTCARE,
			"Times New Roman" );

		// Select the newly created font into
		// the device context (making sure we
		// save a pointer to the old font.)
		CFont *pOldFont = pdc->SelectObject( &Font );

		// Calulate the radii in both directions,
		// and calculate the center point
		// coordinates.
		int nXRadius = rcBounds.Width() / 2;
		int nYRadius = rcBounds.Height() / 2;
		int nCenterX = rcBounds.TopLeft().x + nXRadius;
		int nCenterY = rcBounds.TopLeft().y + nYRadius;

		// Adjust the radii sizes so that the
		// largest text string we'll encounter is
		// subtracted out. This will insure the
		// text doesn't draw outside the view.
		CSize size = pdc->GetTextExtent( "12", 2 );
		nXRadius -= ( size.cx / 2 );
		nYRadius -= ( size.cy / 2 );

		// Draw the 12 clock digits.
		for( int i=1; i<=12; i++ ){

			// Create the clock digit string.
			char szTimeDigits[25];
			wsprintf( szTimeDigits, "%d", i );

			// Get the size of this clock
			// digit string.
			size = pdc->GetTextExtent( szTimeDigits,
				strlen( szTimeDigits ) );

			// Calculate the X distance from the
			// center at which the digits will
			// be drawn.
			int nXLength = (int)
				( (double) nXRadius *
				sin( 6.28 * ( (double) i / 12 ) ) );

			// Calculate the Y distance from the
			// center at which the digits will
			// be drawn.
			int nYLength = (int)
				( (double) nYRadius *
				cos( 6.28 * ( (double) i / 12 ) ) );

			// Draw the digits.
			pdc->TextOut( nCenterX + nXLength - ( size.cx / 2 ),
				nCenterY - (int) nYLength - ( size.cy / 2 ),
				szTimeDigits, strlen( szTimeDigits ) );
			}

		// Select the old font back into the
		// device context.
		pdc->SelectObject( pOldFont );


		// Declare a CPen pointer for the
		// old pen; then create a red, green, and
		// blue pens for the hour, minute, and
		// seconds hands.
		CPen *pOldPen,
			Hour( PS_SOLID, 3, RGB( 255, 0, 0 ) ),
			Minute( PS_SOLID, 3, RGB( 0, 255, 0 ) ),
			Second( PS_SOLID, 3, RGB( 0, 0, 255 ) );

		// Select the hour hand pen.
		pOldPen = pdc->SelectObject( &Hour );
		// Calculate the value with which
		// the length of the hour hand will be
		// calculated.
		double HourValue =
			( (double) ( t.GetHour() <= 12 ?
				t.GetHour() : t.GetHour() - 12 ) +
			( (double) t.GetMinute() / 60.0 ) +
			( (double) t.GetSecond() / 3600.0 ) ) *
			( 6.28 / 12.0 );
		// Draw the hour hand line.
		pdc->MoveTo( nCenterX, nCenterY );
		pdc->LineTo( nCenterX +
			(int) ( ( double) ( ( nXRadius * 50 ) / 100 ) *
			sin( HourValue ) ),
			nCenterY - (int) ( (double) ( ( nYRadius * 50 ) / 100 ) *
			cos( HourValue ) ) );

		// Select the minute hand pen.
		pdc->SelectObject( &Minute );
		// Calculate the value with which
		// the length of the minute hand will be
		// calculated.
		double MinuteValue = ( (double) t.GetMinute() +
			( (double) t.GetSecond() / 60.0 ) ) *
			( 6.28 / 60.0 );
		// Draw the minute hand line.
		pdc->MoveTo( nCenterX, nCenterY );
		pdc->LineTo( nCenterX +
			(int) ( ( double) ( ( nXRadius * 75 ) / 100 ) *
			sin( MinuteValue ) ),
			nCenterY - (int) ( (double) ( ( nYRadius * 75 ) / 100 ) *
			cos( MinuteValue ) ) );

		// Select the second hand pen.
		pdc->SelectObject( &Second );
		// Calculate the value with which
		// the length of the second hand will be
		// calculated.
		double SecondValue = (double) t.GetSecond() *
			( 6.28 / 60.0 );
		// Draw the second hand line.
		pdc->MoveTo( nCenterX, nCenterY );
		pdc->LineTo( nCenterX + (int) ( ( double) nXRadius *
			sin( SecondValue ) ),
			nCenterY - (int) ( (double) nYRadius *
			cos( SecondValue ) ) );

		// Select the old pen back into the
		// device context.
		pdc->SelectObject( pOldPen );

		}

}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::DoPropExchange - Persistence support

void CActiveClockCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: Call PX_ functions for each persistent custom property.

}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::OnResetState - Reset control to default state

void CActiveClockCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl::AboutBox - Display an "About" box to the user

void CActiveClockCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_ACTIVECLOCK);
	dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CActiveClockCtrl message handlers

int CActiveClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (COleControl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	SetTimer( 1, 1000, NULL );
	
	return 0;
}

void CActiveClockCtrl::OnTimer(UINT nIDEvent) 
{

	InvalidateRect( NULL, TRUE );
	UpdateWindow();

	COleControl::OnTimer(nIDEvent);
}

void CActiveClockCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{

	m_nClockType ^= 3;
	InvalidateRect( NULL, TRUE );
	UpdateWindow();

	COleControl::OnLButtonDown(nFlags, point);
}

⌨️ 快捷键说明

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