📄 activeclockctl.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 + -