m3mn0ck
asked on
Problems with C++ ANALOG CLock drawing
Hi i am doing a C++ Active X analog clock
when i draw the hour hand i have no problem and the formula i use to calculate its position works perfect
but when i try to draw the minute hand it always seems off and then whenever a minute passes it jumps about 25 muinutes and draws in an incorrect position
here is the code witht he calculation for the position of the hands.
void CProject5Ctrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if(m_nDisplayStyle == 7)
{
//Creat the Time String
CString m_sTime;
CTime curTime = CTime::GetCurrentTime();
//Format the Time String
m_sTime.Format("%02d:%02d: %02d",
curTime.GetHour(),
curTime.GetMinute(),
curTime.GetSecond());
// Fill the Rectangle with white
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH )GetStockO bject(WHIT E_BRUSH))) ;
// Calculate the Average Width and Height for the Font
int nChars = strlen ( m_sTime );
int nAvWidth = ( rcBounds.Width() / nChars) - 3;
int nAvHeight = rcBounds.Height();
// Create the Font
CFont m_fFont;
m_fFont.CreateFont(nAvHeig ht,nAvWidt h,
0,0,FW_DONTCARE,FALSE,
FALSE,0,DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS,CLIP_ CHARACTER_ PRECIS,
DEFAULT_QUALITY,DEFAULT_PI TCH | FF_DONTCARE,"Arial");
// Assign the font and set a Pointer to the old Font
CFont *pOldFont = pdc->SelectObject( &m_fFont );
// Display the current time
int nCenterX = rcBounds.TopLeft().x;
int nCenterY = rcBounds.TopLeft().y;
pdc->TextOut(nCenterX,nCen terY,m_sTi me);
}
else
{
// Fill the Rectangle with white
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH )GetStockO bject(WHIT E_BRUSH))) ;
// Create a small font to draw the clock digits with.
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,
"Arial" );
// Set the device context to the new font, and
// make a pointer to the old font.
CFont *pOldFont = pdc->SelectObject( &Font );
// Calculate the X and Y radii, and the center point of
// the analog clock face.
int nXRadius = rcBounds.Width() / 2;
int nYRadius = rcBounds.Height() / 2;
int nCenterX = rcBounds.TopLeft().x + nXRadius;
int nCenterY = rcBounds.TopLeft().y + nYRadius;
// Remove the largest possible clock face so your clock
// stays within the circle.
CSize size = pdc->GetTextExtent( "12", 2 );
nXRadius -= ( size.cx / 2 );
nYRadius -= ( size.cy / 2 );
// Draw the clock face.
for( int i=1; i<=12; i++ )
{
// Create the number string for the display.
char szDisplayNum[25];
wsprintf( szDisplayNum, "%d", i );
// Get the size of this clock digit string.
size = pdc->GetTextExtent( szDisplayNum,strlen( szDisplayNum ) );
// Calculate how far from the center of the clockface the
// numbers will be (both X and Y axis).
int nXLength = (int)( (double) nXRadius * sin( (2 * 3.14) * ( (double) i / 12 ) ) );
int nYLength = (int)( (double) nYRadius * cos( (2 * 3.14) * ( (double) i / 12 ) ) );
// Draw the display.
pdc->TextOut( nCenterX + nXLength - ( size.cx / 2 ),nCenterY - (int) nYLength - ( size.cy / 2 ),szDisplayNum, strlen( szDisplayNum ) );
//Pointer for old Pen
CPen Hour;
CPen Minute;
CPen Second;
CPen *pOldPen;
Hour.CreatePen(PS_SOLID,1, RGB(0,0,0) );
Minute.CreatePen(PS_SOLID, 1,RGB(0,25 5,0));
Second.CreatePen(PS_SOLID, 1,RGB(255, 0,0));
// Select the hour hand pen.
pOldPen = pdc->SelectObject( &Hour );
// Calculate the hour display value. Remember to convert from the
// 24-hour to the 12-hour format here.
CTime t = CTime::GetCurrentTime();
double HourValue =
( (double) ( t.GetHour() <= 12 ?
t.GetHour() : t.GetHour() - 12 ) +
( (double) t.GetMinute() / 60.0 ) +
( (double) t.GetSecond() / 3600.0 ) ) *
( (2 * 3.14) / 12.0);
// Now, 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.
pOldPen = pdc->SelectObject( &Minute );
// Calculate the minute display value.
double MinuteValue =
( (double) t.GetMinute() ) +
( (double) t.GetSecond() / 60.0 ) *
( (2 * 3.14) / 60.0);
// Now, 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 ) ) );
}
// Reset the font back to the original.
pdc->SelectObject( pOldFont );
}
}
thanks in advance
when i draw the hour hand i have no problem and the formula i use to calculate its position works perfect
but when i try to draw the minute hand it always seems off and then whenever a minute passes it jumps about 25 muinutes and draws in an incorrect position
here is the code witht he calculation for the position of the hands.
void CProject5Ctrl::OnDraw(CDC*
{
if(m_nDisplayStyle == 7)
{
//Creat the Time String
CString m_sTime;
CTime curTime = CTime::GetCurrentTime();
//Format the Time String
m_sTime.Format("%02d:%02d:
curTime.GetHour(),
curTime.GetMinute(),
curTime.GetSecond());
// Fill the Rectangle with white
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH
// Calculate the Average Width and Height for the Font
int nChars = strlen ( m_sTime );
int nAvWidth = ( rcBounds.Width() / nChars) - 3;
int nAvHeight = rcBounds.Height();
// Create the Font
CFont m_fFont;
m_fFont.CreateFont(nAvHeig
0,0,FW_DONTCARE,FALSE,
FALSE,0,DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS,CLIP_
DEFAULT_QUALITY,DEFAULT_PI
// Assign the font and set a Pointer to the old Font
CFont *pOldFont = pdc->SelectObject( &m_fFont );
// Display the current time
int nCenterX = rcBounds.TopLeft().x;
int nCenterY = rcBounds.TopLeft().y;
pdc->TextOut(nCenterX,nCen
}
else
{
// Fill the Rectangle with white
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH
// Create a small font to draw the clock digits with.
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,
"Arial" );
// Set the device context to the new font, and
// make a pointer to the old font.
CFont *pOldFont = pdc->SelectObject( &Font );
// Calculate the X and Y radii, and the center point of
// the analog clock face.
int nXRadius = rcBounds.Width() / 2;
int nYRadius = rcBounds.Height() / 2;
int nCenterX = rcBounds.TopLeft().x + nXRadius;
int nCenterY = rcBounds.TopLeft().y + nYRadius;
// Remove the largest possible clock face so your clock
// stays within the circle.
CSize size = pdc->GetTextExtent( "12", 2 );
nXRadius -= ( size.cx / 2 );
nYRadius -= ( size.cy / 2 );
// Draw the clock face.
for( int i=1; i<=12; i++ )
{
// Create the number string for the display.
char szDisplayNum[25];
wsprintf( szDisplayNum, "%d", i );
// Get the size of this clock digit string.
size = pdc->GetTextExtent( szDisplayNum,strlen( szDisplayNum ) );
// Calculate how far from the center of the clockface the
// numbers will be (both X and Y axis).
int nXLength = (int)( (double) nXRadius * sin( (2 * 3.14) * ( (double) i / 12 ) ) );
int nYLength = (int)( (double) nYRadius * cos( (2 * 3.14) * ( (double) i / 12 ) ) );
// Draw the display.
pdc->TextOut( nCenterX + nXLength - ( size.cx / 2 ),nCenterY - (int) nYLength - ( size.cy / 2 ),szDisplayNum, strlen( szDisplayNum ) );
//Pointer for old Pen
CPen Hour;
CPen Minute;
CPen Second;
CPen *pOldPen;
Hour.CreatePen(PS_SOLID,1,
Minute.CreatePen(PS_SOLID,
Second.CreatePen(PS_SOLID,
// Select the hour hand pen.
pOldPen = pdc->SelectObject( &Hour );
// Calculate the hour display value. Remember to convert from the
// 24-hour to the 12-hour format here.
CTime t = CTime::GetCurrentTime();
double HourValue =
( (double) ( t.GetHour() <= 12 ?
t.GetHour() : t.GetHour() - 12 ) +
( (double) t.GetMinute() / 60.0 ) +
( (double) t.GetSecond() / 3600.0 ) ) *
( (2 * 3.14) / 12.0);
// Now, 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.
pOldPen = pdc->SelectObject( &Minute );
// Calculate the minute display value.
double MinuteValue =
( (double) t.GetMinute() ) +
( (double) t.GetSecond() / 60.0 ) *
( (2 * 3.14) / 60.0);
// Now, 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 ) ) );
}
// Reset the font back to the original.
pdc->SelectObject( pOldFont );
}
}
thanks in advance
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
:D