MFC tehtäviä syventävät vastaus3

Mureakuha

Loikkaa: valikkoon, hakuun

Tehtävä:

Kirjoita kello. Piirrä kellotaulu ja viisarit LineTo()-funktiolla. Varaa kerran sekunnissa toimiva Timer-kontrolli ja kutsu sieltä WM_PAINT sanomaa, jolloin Windows itse pyyhkii vanhat viisarit pois. Ohjelman täytyy osata skaalata viisarit oikean kokoisiksi riippumatta ikkunan koosta. Kellotaulun ympyrämuodon kaava voidaan laskea sin()- ja cos()-funktioilla. Kun origo on vasemmassa yläkulmassa, kaavan koordinaatit ovat muotoa,

  • Keskipiste: ikkunan_leveys/2-ikkunan_korkeus/2
  • X-koordinaatti: ikkunan_leveys/2+sin(x)*haluttu_etäisyys_keskipisteestä
  • Y-koordinaatti: ikkunan_korkeus/2-cos(x)*haluttu_etäisyys_keskipisteestä

jossa x on haluttu kulma radiaaneissa (00:00 on nolla ja 12:00 on 2*PII radiaania).

CPP

//***********************************************************************
//
//  kello.cpp
//
//***********************************************************************
 
#include <afxwin.h>
#include <math.h> // sin() ja cos()
#include "kello.h"
 
CMyApp myApp;
 
/////////////////////////////////////////////////////////////////////////
// CMyApp luokan aliohjelmien toteutus
 
BOOL CMyApp::InitInstance ()
{
    m_pMainWnd = new CMainWindow;
    m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE;
}
 
/////////////////////////////////////////////////////////////////////////
// CMainWindow luokan aliohjelmien toteutus
 
BEGIN_MESSAGE_MAP (CMainWindow, CWnd)
  ON_WM_CREATE () // lomakkeen luominen
  ON_WM_PAINT () // lomakkeen piirtäminen
  ON_WM_SIZE () // lomakkeen koon muutos
  ON_WM_TIMER () // ajastintapahtuma
  ON_WM_CLOSE () // lopetustapahtuma
END_MESSAGE_MAP ()
 
CMainWindow::CMainWindow ()
{
    CString strWndClass = AfxRegisterWndClass (
        NULL, // ikkunan tyyli
        myApp.LoadStandardCursor (IDC_ARROW), // ikkunan kursori
        (HBRUSH) COLOR_WINDOW, // ikkunan taustan väri
        myApp.LoadStandardIcon (IDI_APPLICATION) // ikkunan ikoni
    ); // rekisteröi oman ikkunaluokan
 
    CreateEx (
        NULL, // lomakkeen lisätyyli
        strWndClass, // lomakkeen ikkunaluokka
        "Kello", // lomakkeen otsikko
        WS_OVERLAPPEDWINDOW, // ikkunan tyyli 
        CW_USEDEFAULT, // aloitus x-positio
        CW_USEDEFAULT, // aloitus y-positio
        300, // alkuleveys
        300, // alkukorkeus
        NULL, // emoikkunan kahva
        NULL, // lomakkeen valikon kahva
        NULL // lisätietoja
    ); // lomakkeen luominen
}
 
int CMainWindow::OnCreate () // lomakkeen luomistapahtuma 
{
    if (!SetTimer (1, 1000, NULL)) // Ajastimen varaus, toimii kerran sekunnissa
    {
        MessageBox ("Ei vapaita ajastimia!", "Virhe", MB_ICONEXCLAMATION | MB_OK) ;
        return -1 ; // ajastimet loppu, ohjelma keskeytyy
    }
    return 0; // kaikki hyvin, 0 palautuu
}
 
void CMainWindow::OnPaint () // lomakkeen piirtotapahtuma
{
  CTime aika = CTime::GetCurrentTime (); // hakee systeemin kellonajan
 
    CPen sininenkyna (PS_SOLID, 2, RGB(0, 0, 128)); // luo tummansinisen kynän
 
    CRect rect;
    GetClientRect (&rect); // lomakkeen koko tallentuu rect-olioon
 
    CPaintDC dc (this); // luo piirtopintaolion
 
    dc.SelectStockObject (BLACK_PEN); //BLACK_PEN on musta varastokynä, ohjelma piirtää sillä kellotaulun
 
    for (double x=0; x<6.2832; x=x+0.5236) // sin() ja cos() käyttävät radiaaneja, 6.2832 == 2*PI
    {
        dc.MoveTo (rect.right/2+int(sin(x)*rect.right*0.45), rect.bottom/2-int(cos(x)*rect.bottom*0.45)); // piirtää kellotaulun
        dc.LineTo (rect.right/2+int(sin(x)*rect.right*0.4), rect.bottom/2-int(cos(x)*rect.bottom*0.4));
    }
 
    dc.SelectObject (sininenkyna) ; //sininenkyna on paksumpi kuin BLACK_PEN, ohjelma piirtää sillä viisarit
 
    dc.MoveTo (rect.right/2, rect.bottom/2); // määrittää LineTo()-funktiota varten alkupisteen
    dc.LineTo (rect.right/2+int(sin(6.2832*aika.GetSecond ()/60)*rect.right*0.34), rect.bottom/2-int(cos(6.2832*aika.GetSecond ()/60)*rect.bottom*0.34)); // sekunnit
  
    dc.MoveTo (rect.right/2, rect.bottom/2); 
    dc.LineTo (rect.right/2+int(sin(6.2832*aika.GetMinute ()/60)*rect.right*0.3), rect.bottom/2-int(cos(6.2832*aika.GetMinute ()/60)*rect.bottom*0.3)); // minuutit
 
    dc.MoveTo (rect.right/2, rect.bottom/2); 
    dc.LineTo (rect.right/2+int(sin(6.2832*aika.GetHour ()/12)*rect.right*0.25), rect.bottom/2-int(cos(6.2832*aika.GetHour ()/12)*rect.bottom*0.25)); // tunnit
}
 
void CMainWindow::OnSize () // lomakkeen koonmuutostapahtuma
{
    InvalidateRgn (NULL, TRUE); // asettaa koko ikkunan epäkelvoksi, Windows generoi WM_PAINT sanoman
}
 
void CMainWindow::OnTimer () // ajastintapahtuma
{
    InvalidateRgn (NULL, TRUE); // asettaa koko ikkunan epäkelvoksi, Windows generoi WM_PAINT sanoman
}
 
void CMainWindow::OnClose () // lopetustapahtuma
{
    KillTimer (1); // poistaa Timer:n käytöstä ennen lopetusta, ei tuhlaa resursseja 
    CWnd::OnClose (); // lopettaa ohjeman
}

H

//***********************************************************************
//
//  kello.h
//
//***********************************************************************
 
class CMyApp : public CWinApp // CMyApp periytetään MFC:n ohjelma-yliluokasta
{
    public: // aliohjelmajäsenten esittely
        virtual BOOL InitInstance (); // ohjelman instanssin initialisaatio
};
 
class CMainWindow : public CWnd // CMainWindow periytetään MFC:n ikkuna-yliluokasta
{
    public: // aliohjelmajäsenten esittely
        CMainWindow (); // ikkunan luontialiohjelma
 
    protected: // aliohjelmajäsenten esittely
        afx_msg int OnCreate (); // luomisaliohjelma
        afx_msg void OnPaint (); // piirtoaliohjelma
        afx_msg void OnTimer (); // ajastintapahtuma
        afx_msg void OnClose (); // lopetustapahtuma
        afx_msg void OnSize (); // lomakkeen koon muutos
        DECLARE_MESSAGE_MAP () // MESSAGE MAP:n esittely
};
Tämän dokumentin kopiointi, levittäminen sekä muokkaaminen on sallittua GNU Free Documentation Licensen version 1.2 tai uudemman Free Software Foundationin julkaiseman version mukaisesti, ilman muuttumattomuuslauseketta tai kansitekstejä. Tätä koskee vastuuvapaus.
Kopio lisenssistä (englanniksi) löytyy täältä.

Alkuperäinen (c) Petteri Hämäläinen

Henkilökohtaiset työkalut