Corso di Visual C++

La cattura del mouse in azione

 

Vediamo in questa puntata come implementare le conoscenze acquisite negli scorsi articoli per metter su un programma molto banale per tracciare linee colorate usando la cattura del mouse.

Innanzitutto creiamo un'applicazione MFC standard Single Document Interface e chiamiamola Prg27.

Aggiungiamo i seguenti membri di dati nella dichiarazione della classe della vista ( CPrg27View.h ):

BOOL m_bTracciamentoInCorso;

CPoint m_ptOrigine;

CPoint m_ptDestinazione;

I nomi sembrano alquanto autoesplicativi e non penso servano spiegazioni.

Agganciamo i gestori dei messaggi WM_LBUTTONDOWN, WL_LBUTTONUP e WM_MOUSEMOVE con il Wizard e modifichiamoli come riportato di seguito:

 

void CPrg27View::OnLButtonDown(UINT nFlags, CPoint point)

{

m_bTracciamentoInCorso=TRUE;

SetCapture();

m_ptOrigine=point;

m_ptDestinazione=point;

CView::OnLButtonDown(nFlags, point);

}

void CPrg27View::OnLButtonUp(UINT nFlags, CPoint point)

{

static int iColor=0;

COLORREF crfColor;

if (m_bTracciamentoInCorso)

{

m_bTracciamentoInCorso=FALSE;

if (GetCapture()==this)

ReleaseCapture();

CClientDC dc(this);

DisegnaRubberBand(&dc,m_ptOrigine,m_ptDestinazione); //cancelliamo la rubber band

switch (iColor)

{

case 0: crfColor=RGB(0,0,0);

break;

case 1: crfColor=RGB(255,0,0);

break;

case 2: crfColor=RGB(0,255,0);

break;

case 3: crfColor=RGB(0,0,255);

break;

}

iColor=++iColor%4;

CPen pen(PS_SOLID,8,crfColor);

dc.SelectObject(&pen);

dc.MoveTo(m_ptOrigine);

dc.LineTo(m_ptDestinazione); //e tracciamo la linea finale

}

CView::OnLButtonUp(nFlags, point);

}

void CPrg27View::OnMouseMove(UINT nFlags, CPoint point)

{

if (m_bTracciamentoInCorso)

{

CClientDC dc(this);

DisegnaRubberBand(&dc,m_ptOrigine,m_ptDestinazione); //cancelliamo la vecchia rubber band

m_ptDestinazione=point;

DisegnaRubberBand(&dc,m_ptOrigine,m_ptDestinazione); //traccia la nuova rubber band

}

CView::OnMouseMove(nFlags, point);

}

I gestori sono molto semplici, per tal motivo ho aggiunto una piccola complicazione in OnLButtonUp per disegnare ciclicamente linee di colore nero, rosso, verde e blu. Per 'ricordare' il colore precedentemente utilizzato ho preferito non usare una variabile globale, bensì una locale statica ( senza problemi di effetti collaterali "Side Effects" ).

Negli ultimi due gestori richiamo la semplice funzione helper ( ausiliaria ) DisegnaRubberBand per disegnare le vere e proprie rubber band:

void CPrg27View::DisegnaRubberBand(CClientDC *pDC, CPoint ptOrig, CPoint ptDest)

{

int temp=pDC->SetROP2(R2_NOT);

pDC->MoveTo(ptOrig);

pDC->LineTo(ptDest);

pDC->SetROP2(temp);

}

Questa non fa altro che impostare una particolare modalità di disegno tramite CDC::SetROP2() e poi disegnare la nuova rubber band. R2_NOT è una modalità che permette di disegnare i pixel del colore inverso di quello dello sfondo, non di un colore particolare. Questo fa si che disegnando due linee sovrapposte con tale attributo l'effetto è il medesimo di quello che avremmo se non avessimo disegnato alcunché. Alla fine delle operazioni di disegno si provvede poi a ripristinare il contesto di dispositivo con i valori originali.

Il programma di per se è molto semplice e non è stata usata alcuna sofisticazione particolare: abbiamo solo messo in pratica le ultime lezioni.

Per scaricare il progetto Prg27, clicca qui.

Vorrei far osservare che quando si usa la cattura del mouse, nelle funzioni di gestione degli eventi, i valori dei membri di dati degli oggetti CPoint, possono anche essere negativi o maggiori dell'area client. Questo per il motivo che potete facilmente immaginare essere che il mouse esce fuori dall'area della finestra.

Nella prossima puntata vedremo un po' di 'sfizioserie' con il mouse: cambiarne la forma, l'intervallo di doppio click, recuperare lo stato dei pulsanti della tastiera al momento della generazione dei mouse event...

 

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