[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Problems with C++ ANALOG CLock drawing

Posted on 2004-11-14
2
Medium Priority
?
1,194 Views
Last Modified: 2012-08-14
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)GetStockObject(WHITE_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(nAvHeight,nAvWidth,
                                    0,0,FW_DONTCARE,FALSE,
                                    FALSE,0,DEFAULT_CHARSET,
                                    OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,
                                    DEFAULT_QUALITY,DEFAULT_PITCH | 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,nCenterY,m_sTime);
   }      
   
   else
   {
        // Fill the Rectangle with white            
        pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_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,255,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
0
Comment
Question by:m3mn0ck
2 Comments
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 1000 total points
ID: 12579362
I see a big error in your code. The for loop (1..12), not only draw the clock face but it repeateadly draw the hour/minutes/seconds hands. You need to terminater your for loop before.

// 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 ) );

      }  // <------------------ Terminate your for loop here

     // NOW DRAW HANDS ONLY ONCE    
          //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,255,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)  +          // <----- USE MODULUS OPERATOR HERE
           (double) t.GetMinute() / 60.0  +         // TOO MUCH PARENTHESIS
           (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 * 0.5 * sin(HourValue) ),
                              nCenterY - (int) ( (double)nYRadius * 0.5 * 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 * 0.75 * sin( MinuteValue) ),
                               nCenterY - (int) ( (double) nYRadius * 0.75 * cos( MinuteValue) ) );

//       }  <---- Don't need this ending brace

0
 

Author Comment

by:m3mn0ck
ID: 12580172
Thanks a lot Jaime i really appreciate it

:D
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Make the most of your online learning experience.
The SignAloud Glove is capable of translating American Sign Language signs into text and audio.
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Starting up a Project

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question