Corso di Visual C++

I pulsanti del mouse e la posizione

 

Per sapere quali pulsanti del mouse erano stati premuti al momento dell'invio di un messaggio del mouse, oltre che controllare il parametro nFlags del gestore, possibile richiamare le funzioni ::GetKeyState e ::GetAsincKeyState con i parametri VK_LBUTTON, VK_MBUTTON, VK_RBUTTON o qualsiasi altro codice di tasto virtuale che identifichi i tasti delle tastiera.
Per semplificare, un valore di ritorno negativo significa che il tasto premuto, se 0 il tasto non premuto.
Nei dettagli invece accade che il bit di ordine alto 1, se il tasto premuto, altrimenti 0 se non lo .
Quando il bit di ordine alto di un numero (il primo dalla sinistra) 1, allora il numero assume segno negativo.
Inoltre se il bit di ordine basso 1 (numero dispari), allora il tasto con il codice virtuale specificato attivato. Un tasto come CAPS LOCK o BLOCK NUM attivato se l'indicatore sulla tastiera acceso. Se il tasto non attivo, allora il bit di ordine basso zero (numero pari) e l'indicatore luminoso spento.

La differenza tra ::GetKeyState e ::GetAsincKeyState sta nel fatto che la prima sincrona cio restituisce lo stato del pulsante al momento dell'invio del messaggio di tastiera relativo a quel pulsante; per tale motivo andrebbe per lo pi utilizzato in un gestore di messaggi della tastiera.
Lo stato di ritorno da tale funzione cambia non appena un thread legge dei messaggi di tasto dalla sua coda dei messaggi. Tale stato non riflette lo stato a livello di interrupt associato con l'hardware; per avere questa informazione usare ::GetAsyncKeyState.
Quest'ultima infatti asincrona e funziona in tempo reale restituendo lo stato del pulsante al momento dell'invocazione della funzione.

possibile anche 'costringere' il cursore a muoversi in un'area predefinita e vincolarlo a restarci fino a quando non lo si sblocca da tale situazione. Per definire un'area rettangolare all'interno del quale si vuole vincolare il cursore si pu utilizzare la funzione ::ClipCursor; il suo prototipo il seguente:
BOOL ClipCursor(CONST RECT lpRect);
Il valore di ritorno diverso da zero se non ci sono errori, mentre il parametro passato un puntatore ad una struttura RECT che definisce appunto l'area di movimento del cursore. Se tale parametro NULL, si sblocca il cursore abilitandolo ad usare l'intero schermo.
Come al solito la raccomandazione di ripristinare lo stato del cursore (essendo una risorsa condivisa) prima di cedere il controllo ad altre applicazioni o finestre. In caso contrario il mouse potrebbe non funzionare correttamente.

Vediamo adesso come possibile recuperare la posizione del mouse dall'esterno di una funzione di gestione del mouse.
La funzione chiave ::GetMessagePos, questa ritorna una DWORD contenente le coordinate del mouse (in coordinate di schermo) al momento dell'invio dell'ultimo messaggio recuperato da ::GetMessage.
Ad esempio se ci troviamo nel gestore di messaggio di WM_SETCURSOR e richiamiamo ::GetMessagePos le coordinate del mouse sono relative al momento in cui tale messaggio stato prelevato dalla coda; in seguito a tale prelievo verr poi richiamata la funzione in cui ci troviamo.

Le coordinate ritornate da ::GetMessagePos necessitano di un paio di trasformazioni, primo perch non sono in un oggetto CPoint, ma in una DWORD e secondo perch sono in coordinate di schermo.
Vediamo un po' queste trasformazioni che vi serviranno spessissimo nella vostra vita di programmatori:

DWORD dwPos= ::GetMessagePos();
CPoint pt (LOWORD(dwPos), HIWORD (dwPos));
ScreenToClient(&pt);

La prima riga di codice serve a recuperare le coordinate del mouse, la seconda a convertire la DWORD in un oggetto CPoint e la terza infine trasforma da coordinate di schermo a coordinate client.
Nella seconda riga di codice sono da notare le due macro LOWORD e HIWORD che ritornano della DWORD ( doppia parola ) la WORD bassa e quella alta. Come facilmente intuibile, della DWORD la parte alta contiene le coordinate orizzontali, mentre la parte bassa quelle verticali.

 

Piccolissima nota:
La parte alta quella pi significativa, quella che in pratica quando varia fa cambiare maggiormente il valore del numero. Ad esempio in un numero di 4 bit se il primo bit di ordine alto passa da 0 a 1, il numero aumenta di 16 unit ( 2^4 ), se invece cambia il bit di ordine pi basso, il valore del numero cambia di un'unit ( 2^0 ).

Usando le macro LOWORD e HIWORD per potrebbero esserci dei problemi con i sistemi con monitor multipli, si consiglia quindi di usare la macro MAKEPOINTS che ritorna una struttura di tipo POINTS.
La procedura corretta quindi diventa:

DWORD dwPos= ::GetMessagePos();
POINTS pts = MAKEPOINTS(dwPos);
CPoint pt (pts.x,pts.y);
ScreenToClient(&pt);


Per la gestione del mouse, questo tutto, dalla prossima puntata inizieremo a descrivere in dettaglio la gestione della tastiera.

 

 

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