Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Classe OROLOGIO - main.cpp

main.cpp

Caricato da: AldoBaldo
Scarica il programma completo

  1. /***============================================================================
  2. Questo programma serve unicamente per testare l'impiego della classe OROLOGIO.
  3. Dal momento che, a titolo puramente esemplificativo, usa un semplice timer
  4. gestito tramite callback, la precisione dell'ora indicata NON e' assicurata.
  5. =============================================================================**/
  6.  
  7.  
  8. #include <windows.h>
  9. #include <gdiplus.h>
  10. using namespace Gdiplus;
  11. #include "orologio.h"
  12.  
  13.  
  14. // === COSTANTI ================================================================
  15.  
  16. const char kStrNomeClasse[] = "ClasseTestOrogologio";
  17. const char kStrNomeProgrm[] = "Test classe orologio";
  18. const int kWFinestra        = 800;
  19. const int kHFinestra        = 450;
  20. const int kMargine          = 30;
  21. const unsigned int kIdTimer = 1000;
  22.  
  23.  
  24. // === VARIABILI GLOBALI =======================================================
  25.  
  26. OROLOGIO *gOPtr1 = NULL;    // alias globali degli oggetti locali OROLOGIO
  27. OROLOGIO *gOPtr2 = NULL;    // definiti in WinMain()
  28.  
  29.  
  30. // === PROTOTIPI DI FUNZIONI ===================================================
  31.  
  32. LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wPar, LPARAM lPar );
  33. VOID CALLBACK TimerProc( HWND hwnd,     UINT uMsg, UINT idEvent, DWORD dwTime );
  34. void ModificaSecondoOrologio( void );
  35. bool RegistraClasse( HINSTANCE hInst );
  36. bool CreaFinestra( HWND *hwnd, HINSTANCE hInst );
  37. bool InizializzaGdiPlus( void );
  38. void DismettiGdiPlus( void );
  39. void Errore( int codice, HWND hwnd = NULL );
  40. void Errore( const char *msg, HWND hwnd = NULL );
  41.  
  42.  
  43. /*==============================================================================
  44. Funzione d'accesso al programma
  45. ==============================================================================*/
  46.  
  47. int WINAPI WinMain(
  48.     HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nCmdShow ) {
  49.     HWND hwnd = NULL;
  50.     MSG msg   = {0};
  51.  
  52.     if( !RegistraClasse(hInst) )     { Errore(1); return 0; }
  53.     if( !CreaFinestra(&hwnd,hInst) ) { Errore(2); return 0; }
  54.     if( !InizializzaGdiPlus() )      { Errore(3); return 0; }
  55.  
  56.     ShowWindow( hwnd, nCmdShow );
  57.  
  58.     try {
  59.         Rect ro( kMargine, kMargine,
  60.                  kWFinestra/2-1.5*kMargine,
  61.                  kHFinestra-2*kMargine );
  62.  
  63.         OROLOGIO o1( hwnd, &ro );
  64.  
  65.         ro.X += kWFinestra/2-0.5*kMargine; // sposta il Rect
  66.  
  67.         OROLOGIO o2( hwnd, &ro );
  68.  
  69.         gOPtr1 = &o1; // definisce un alias globale dell'oggetto
  70.         gOPtr2 = &o2; // definisce un alias globale dell'oggetto
  71.  
  72.         // a titolo di prova, modifica alcune
  73.         // caratteristiche del secondo orologio
  74.         ModificaSecondoOrologio();
  75.  
  76.         TimerProc( NULL, 0, kIdTimer, 0x00000000 );
  77.  
  78.         while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {
  79.             TranslateMessage( &msg );
  80.             DispatchMessage( &msg );
  81.         }
  82.  
  83.         gOPtr1 = NULL;
  84.         gOPtr2 = NULL;
  85.     } catch ( const char *strErr ) {
  86.         Errore( strErr, hwnd );
  87.     } catch( ... ) {
  88.         Errore(4);
  89.     }
  90.  
  91.     DismettiGdiPlus();
  92.     return 0;
  93. }
  94.  
  95. /*==============================================================================
  96. Window Procedure per la finestra principale del programma. Tra le altre cose...
  97.     1. imposta il timer che chiama TimerProc una ventina di volte al secondo per
  98.        ridisegnare l'orologio in base all'ora corrente
  99.     2. richiede agli orologi di trasferire il proprio offscreen a schermo ogni
  100.        qualvolta si riceva un messaggio di tipo WM_PAINT
  101. ==============================================================================*/
  102.  
  103. LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wPar, LPARAM lPar ) {
  104.     switch( msg ) {
  105.  
  106.         case WM_CREATE:
  107.             // il sistema chiama TimerProc +/- 20 volte al sec
  108.             SetTimer( hwnd, kIdTimer, 50, TimerProc );
  109.             break;
  110.  
  111.         case WM_PAINT: {
  112.             PAINTSTRUCT ps;
  113.             BeginPaint( hwnd, &ps );
  114.             // aggiorna le immagini già negli offscreen,
  115.             // senza ridisegnare gli orologi da zero
  116.             if( gOPtr1 ) gOPtr1->Aggiorna();
  117.             if( gOPtr2 ) gOPtr2->Aggiorna();
  118.             EndPaint( hwnd, &ps );
  119.             } break;
  120.  
  121.         case WM_CLOSE:
  122.             KillTimer( hwnd, kIdTimer );
  123.             PostQuitMessage( 0 );
  124.             break;
  125.  
  126.         default:
  127.             return DefWindowProc( hwnd, msg, wPar, lPar );
  128.     }
  129.  
  130.     return 0;
  131. }
  132.  
  133.  
  134. /*==============================================================================
  135. Chiamata dal sistema ad ogni scadenza del timer kIdTimer (approssimativamente
  136. 20 volte al secondo) e verifica l'ora locale. Se l'ora di sistema e' cambiata
  137. rispetto all'ultima verifica aggiorna i due oggetti di classe OROLOGIO affinche'
  138. mostrino rispettivamente l'ora locale e quella UTC.
  139. ==============================================================================*/
  140.  
  141. VOID CALLBACK TimerProc( HWND hwnd,     UINT uMsg, UINT idEvent, DWORD dwTime ) {
  142.     if( gOPtr1 == NULL || gOPtr2 == NULL ) return;
  143.        
  144.     SYSTEMTIME st, lt; // [s]ystem [t]ime (UTC) e [l]ocal [t]ime
  145.  
  146.     GetLocalTime( &lt );  // ora locale
  147.  
  148.     // solo se l'ora e' effettivamente cambiata...
  149.     if( gOPtr1->RicavaSecondo() != lt.wSecond ) {
  150.         GetLocalTime( &lt );  // ora locale, di nuovo
  151.         GetSystemTime( &st ); // ora UTC
  152.  
  153.         gOPtr1->ImpostaOra( lt.wHour, lt.wMinute, lt.wSecond );
  154.         gOPtr2->ImpostaOra( st.wHour, st.wMinute, st.wSecond );
  155.        
  156.         gOPtr1->Traccia( false ); // "false" per evitare che il primo orologio
  157.         gOPtr2->Traccia( false ); // venga riportato sullo schermo fino al
  158.                                   // momento in cui anche il secondo orologio
  159.                                   // e' pronto in offscreen
  160.  
  161.         gOPtr1->Aggiorna();  // riporta sullo schermo entrambi gli orologi col
  162.         gOPtr2->Aggiorna();  // minimo intervallo di tempo possibile tra i due
  163.     }
  164. }
  165.  
  166.  
  167. /*==============================================================================
  168. A titolo di esempio, modifica alcune delle caratteristiche del secondo orologio.
  169. ==============================================================================*/
  170.  
  171. void ModificaSecondoOrologio( void ) {
  172.     if( gOPtr2 ) {
  173.         gOPtr2->ImpostaColoreSfondoOggetto( 0x33EEEEEE );
  174.         gOPtr2->SpessoreBordoQuadrante( 2.0f*gOPtr2->SpessoreBordoQuadrante() );
  175.         gOPtr2->cSfondoQuadrante = 0xEEFFCC00;
  176.         gOPtr2->cBordoQuadrante = 0xCC006699;
  177.         gOPtr2->cNumeriQuadrante = gOPtr2->cBordoQuadrante;
  178.         gOPtr2->c[kLancettaOre] = gOPtr2->cBordoQuadrante;
  179.         gOPtr2->s[kLancettaOre] *= 2.0f;
  180.         gOPtr2->l[kLancettaOre] *= 0.75f;
  181.         gOPtr2->c[kLancettaMinuti] = gOPtr2->cBordoQuadrante;
  182.         gOPtr2->s[kLancettaMinuti] *= 1.75f;
  183.         gOPtr2->l[kLancettaMinuti] *= 0.825f;
  184.         gOPtr2->c[kLancettaSecondi] = gOPtr2->cBordoQuadrante;
  185.         gOPtr2->s[kLancettaSecondi] *= 2.0f;
  186.         gOPtr2->l[kLancettaSecondi] *= 0.85f;
  187.         gOPtr2->c[kMarcatoriOre] = gOPtr2->cBordoQuadrante;
  188.         gOPtr2->s[kMarcatoriOre] *= 2.0f;
  189.         gOPtr2->c[kMarcatoriMinuti] = gOPtr2->cBordoQuadrante;
  190.         gOPtr2->s[kMarcatoriMinuti] *= 2.0f;
  191.     }
  192. }
  193.  
  194.  
  195. /*==============================================================================
  196. Registra la classe per la finestra principale del programma.
  197. ==============================================================================*/
  198.  
  199. bool RegistraClasse( HINSTANCE hInst ) {
  200.     WNDCLASS wc = {0};
  201.  
  202.     wc.lpfnWndProc   = WndProc;
  203.     wc.hInstance     = hInst;
  204.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  205.     wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
  206.     wc.lpszClassName = kStrNomeClasse;
  207.  
  208.     return( RegisterClass(&wc) != 0 );
  209. }
  210.  
  211.  
  212. /*==============================================================================
  213. Crea la finestra principale del programma, centrandola sullo schermo.
  214. ==============================================================================*/
  215.  
  216. bool CreaFinestra( HWND *hwnd, HINSTANCE hInst ){
  217.     DWORD stile = WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE;
  218.     RECT r = { 0, 0, kWFinestra, kHFinestra };
  219.  
  220.     AdjustWindowRect( &r, stile, FALSE );
  221.  
  222.     OffsetRect( &r,
  223.         -r.left+(GetSystemMetrics(SM_CXSCREEN)-(r.right-r.left))/2,
  224.         -r.top+(GetSystemMetrics(SM_CYSCREEN)-(r.bottom-r.top))/2 );
  225.  
  226.     *hwnd = CreateWindow( kStrNomeClasse, kStrNomeProgrm, stile,
  227.         r.left, r.top, r.right-r.left, r.bottom-r.top, 0, 0, hInst, NULL );
  228.  
  229.     return *hwnd != NULL;
  230. }
  231.  
  232. // === FUNZIONI PER L'INIZIALIZZAZIONE E LA DISMISSIONE DI GDI+ ================
  233.  
  234. static ULONG_PTR gdiplusToken = 0;
  235.  
  236. bool InizializzaGdiPlus( void ) {
  237.     GdiplusStartupInput gdiplusStartupInput;
  238.  
  239.     if( GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL ) != Ok )
  240.         return false;
  241.     return true;
  242. }
  243.  
  244. void DismettiGdiPlus( void ) {
  245.     GdiplusShutdown( gdiplusToken );
  246. }
  247.  
  248. // === FUNZIONI PER LA NOTIFICA DEGLI ERRORI ===================================
  249.  
  250. void Errore( int codice, HWND hwnd ) {
  251.     static const char *strErr[] = {
  252.         "Classe non registrata. ",
  253.         "Finestra non creata. ",
  254.         "GDI+ non inizializzato. ",
  255.         "Memoria non allocata. "
  256.     };
  257.  
  258.     if( codice > -1 && codice < 4 ) {
  259.         MessageBox( hwnd, strErr[codice], kStrNomeProgrm, MB_OK|MB_ICONERROR );
  260.     }
  261.     else {
  262.         char msg[48];
  263.         wsprintf( msg, "Si e' verificato un errore! Codice #%d", codice );
  264.         MessageBox( hwnd, msg, kStrNomeProgrm, MB_OK|MB_ICONERROR );
  265.     }
  266. }
  267.  
  268. void Errore( const char *msg, HWND hwnd ) {
  269.     MessageBox( hwnd, msg, kStrNomeProgrm, MB_OK|MB_ICONERROR );
  270. }