Corso di Visual C++

Gli strumenti per la grafica I

 

Nell'ultima puntata abbiamo esplorato fino in fondo il comportamento della funzione OnDraw, in questa vedremo come sfruttare le conoscenze acquisite con un esempio pratico.

Quello che vogliamo fare è disegnare un rettangolo di 200x200 pixel al centro della finestra e quindi far si che quando si clicca con il mouse al suo interno cambi il suo colore di riempimento.

Innanzitutto creiamo un nuovo progetto e chiamiamolo prg7; se non ricordate come fare, seguite i passi mostrati nell'articolo 2.

Mappate il messaggio WM_LBUTTONDOWN come spiegato nell'ultima puntata e poi modificate il codice generato da AppWizard seguendo le istruzioni di seguito:

  1. Nel file di dichiarazione della vista ( CPrg7View.h ) aggiungete le seguenti variabili membro :
  2. private:

    CRect m_rectRect;

    CSize m_sizeRect;

    int m_nColor;

    La prima variabile è un oggetto della classe CRect e conterrà le coordinate per disegnare un rettangolo sullo schermo, la seconda è una istanziazione della classe CSize che conterrà le dimensioni del rettangolo, mentre la terza è una variabile di tipo intero che conterrà il codice del colore per il pennello di riempimento.

    Lo saprete bene, visto che siete espertissimi di C++, che le istanziazioni di una classe sono le dichiarazioni degli oggetti di tale classe; tali oggetti vivono nel segmento dati del programma e quando l'oggetto genitore viene distrutto, vengono automaticamente deallocati anche questi ultimi (al contrario degli oggetti allocati dinamicamente).

    Osservate che per convenzione le variabili di una classe sono dette variabili membro o membri di dati e sono dichiarate anteponendo al loro nome il suffisso m_; questa convenzione è quella della libreria MFC e noi la seguiremo per il resto del corso.

    1. Nel costruttore della vista aggiungete le inizializzazioni delle variabili in questo modo che è il più semplice:
    2. CPrg7View::CPrg7View()

      {

      // TODO: add construction code here

      m_sizeRect =CSize(200,200);

      m_nColor=WHITE_BRUSH;

      }

    3. Ora dobbiamo calcolare la posizione del rettangolo per centrarlo nella finestra; a tal scopo ci occorre la dimensione della vista e poi dobbiamo far si che all'avvio del programma il rettangolo compaia subito nella giusta posizione.

    Ci sarà d'aiuto effettuare un override ( non è lo stesso di mappare ) della funzione virtuale OnInitialUpdate.

    Questa funzione è l'ultima che viene chiamata prima che venga visualizzata la finestra, ed in questo punto possiamo eseguire molte inizializzazioni per gli oggetti grafici.

    Per fare ciò possiamo servirci di ClassWizard oppure, ora che siete esperti, cliccate sulla voce CPrg7View con il pulsante destro del mouse, selezionate la voce Add Virtual Function e quindi cliccate su OnInitialUpdate.

    Scrivete il seguente codice:

    void CPrg7View::OnInitialUpdate()

    {

    CView::OnInitialUpdate();

    // TODO: Add your specialized code here and/or call the base class

    CRect rectTemp;

    GetClientRect(&rectTemp); //recupero dimensioni area visibile

    //calcolo centro area visibile

    CPoint ptCentro((rectTemp.right-rectTemp.left)/2,(rectTemp.bottom-rectTemp.top)/2);

    //calcolo origine (angolo sup-sx del rettangolo)

    CPoint ptOrigine(ptCentro.x-m_sizeRect.cx/2,ptCentro.y-m_sizeRect.cy/2);

    //costruzione del rettangolo specificando origine e dimensione

    m_rectRect=CRect(ptOrigine,m_sizeRect);

    }

    Il codice con i commenti è abbastanza autoesplicativo, sappiate solo che il sistema di assi cartesiani utilizzato ha origine nell'angolo superiore sinistro dello schermo e ha gli assi positivi di X e Y rispettivamente orientati verso destra e verso il basso.

    Inoltre la funzione GetClientRect recupera le dimensioni dell'area visibile 'della vista' e le inserisce nell'oggetto CRect passato per riferimento.

    Nell'ultima istruzione infine vedete come abbiamo assegnato il valore a m_rectRect? Ci sono altri 6 modi diversi di farlo e siccome vi tornerà utile la loro conoscenza, prendete informazioni dall'help in linea.

    Abbiamo qui utilizzate per la prima volta anche le classi CPoint e CSize vediamo come funzionano:

    Un oggetto di tipo CPoint è composto da due variabili membro: x e y che indicano la posizione del punto, mentre un oggetto di tipo CSize contiene le due variabili membro cx e cy che indicano le dimensioni orizzontali e verticali.

    Gli oggetti CPoint, CSize e CRect possono essere combinati assieme con le operazioni aritmetiche di somma e differenza ( non prodotti e divisioni) nonché alcuni operazioni logiche come and (&), or (|) e not (!).

    Ad esempio sommando un oggetto CPoint ad un CRect, si sposta quest'ultimo di un quantità pari alle coordinate x e y del punto:


    CRect rect1(100, 235, 200, 335);
    CPoint pt(35, 65);
    CRect rect2(135, 300, 235, 400);

    rect1 += pt;

    ASSERT(rect1 == rect2);

    La macro ASSERT verifica che due oggetti siano uguali, in caso contrario interrompe l'esecuzione del programma.

    Provate ora da voi a completare il programma aggiungendo almeno la funzione che disegna il rettangolo sullo schermo, se non ci riuscite vedrete come farlo alla prossima puntata.

    PS: Vi consiglio di fare esperimenti con le operazioni tra le classi elementari viste sopra, in molte occasioni vi potranno far risparmiare righe di codice da correggere!

     

    Torna all'indice Generale del corso di Corso di Visual C++ di Software Planet