Condividi tramite


Operazioni varie del mouse

Le sezioni precedenti hanno illustrato i clic del mouse e lo spostamento del mouse. Ecco alcune altre operazioni che possono essere eseguite con il mouse.

Trascinamento degli elementi dell'interfaccia utente

Se l'interfaccia utente supporta il trascinamento degli elementi dell'interfaccia utente, è presente un'altra funzione che devi chiamare nel gestore dei messaggi del mouse verso il basso: DragDetect. La funzione DragDetect restituisce TRUE se l'utente avvia un movimento del mouse che deve essere interpretato come trascinamento. Il codice seguente illustra come usare questa funzione.

    case WM_LBUTTONDOWN: 
        {
            POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
            if (DragDetect(m_hwnd, pt))
            {
                // Start dragging.
            }
        }
        return 0;

Ecco l'idea: quando un programma supporta il trascinamento della selezione, non si vuole che ogni clic del mouse venga interpretato come trascinamento. In caso contrario, l'utente potrebbe trascinare accidentalmente qualcosa quando ha semplicemente lo scopo di fare clic su di esso (ad esempio, per selezionarlo). Ma se un mouse è particolarmente sensibile, può essere difficile mantenere il mouse perfettamente mentre si fa clic. Pertanto, Windows definisce una soglia di trascinamento di alcuni pixel. Quando l'utente preme il pulsante del mouse, non viene considerato un trascinamento a meno che il mouse non supera questa soglia. La funzione DragDetect verifica se questa soglia viene raggiunta. Se la funzione restituisce TRUE, è possibile interpretare il clic del mouse come trascinamento. In caso contrario, non farlo.

Nota

Se DragDetect restituisce FALSE, Windows elimina il messaggio WM_LBUTTONUP quando l'utente rilascia il pulsante del mouse. Pertanto, non chiamare DragDetect a meno che il programma non sia attualmente in una modalità che supporta il trascinamento. Ad esempio, se è già selezionato un elemento trascinabile dell'interfaccia utente. Alla fine di questo modulo verrà visualizzato un esempio di codice più lungo che usa la funzione DragDetect .

 

Limiti del cursore

In alcuni casi potrebbe essere necessario limitare il cursore all'area client o a una parte dell'area client. La funzione ClipCursor limita lo spostamento del cursore a un rettangolo specificato. Questo rettangolo viene specificato nelle coordinate dello schermo, anziché nelle coordinate client, quindi il punto (0, 0) indica l'angolo superiore sinistro dello schermo. Per convertire le coordinate client in coordinate dello schermo, chiamare la funzione ClientToScreen.

Il codice seguente limita il cursore all'area client della finestra.

    // Get the window client area.
    RECT rc;
    GetClientRect(m_hwnd, &rc);

    // Convert the client area to screen coordinates.
    POINT pt = { rc.left, rc.top };
    POINT pt2 = { rc.right, rc.bottom };
    ClientToScreen(m_hwnd, &pt);
    ClientToScreen(m_hwnd, &pt2);
    SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);

    // Confine the cursor.
    ClipCursor(&rc);

ClipCursor accetta una struttura RECT , ma ClientToScreen accetta una struttura POINT . Un rettangolo è definito dai punti superiore sinistro e inferiore destro. È possibile limitare il cursore a qualsiasi area rettangolare, incluse le aree esterne alla finestra, ma il limite del cursore all'area client è un modo tipico per usare la funzione. Limitare il cursore a un'area completamente esterna alla finestra sarebbe insolito e gli utenti probabilmente lo percepiscono come bug.

Per rimuovere la restrizione, chiamare ClipCursor con il valore NULL.

ClipCursor(NULL);

Eventi di rilevamento del mouse: passaggio del mouse e uscita

Per impostazione predefinita, altri due messaggi del mouse sono disabilitati, ma possono essere utili per alcune applicazioni:

  • WM_MOUSEHOVER: il cursore è posizionato sull'area client per un periodo di tempo fisso.
  • WM_MOUSELEAVE: il cursore ha lasciato l'area client.

Per abilitare questi messaggi, chiamare la funzione TrackMouseEvent .

    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(tme);
    tme.hwndTrack = hwnd;
    tme.dwFlags = TME_HOVER | TME_LEAVE;
    tme.dwHoverTime = HOVER_DEFAULT;
    TrackMouseEvent(&tme);

La struttura TRACKMOUSEEVENT contiene i parametri per la funzione. Il membro dwFlags della struttura contiene flag di bit che specificano i messaggi di rilevamento a cui si è interessati. È possibile scegliere di ottenere sia WM_MOUSEHOVER che WM_MOUSELEAVE, come illustrato di seguito o solo uno dei due. Il membro dwHoverTime specifica per quanto tempo il mouse deve passare il puntatore del mouse prima che il sistema generi un messaggio al passaggio del mouse. Questo valore viene specificato in millisecondi. La costante HOVER_DEFAULT significa usare l'impostazione predefinita del sistema.

Dopo aver visualizzato uno dei messaggi richiesti, la funzione TrackMouseEvent viene reimpostata. È necessario chiamarlo di nuovo per ottenere un altro messaggio di rilevamento. Tuttavia, è necessario attendere fino al successivo messaggio di spostamento del mouse prima di chiamare di nuovo TrackMouseEvent . In caso contrario, la finestra potrebbe essere inondata con messaggi di rilevamento. Ad esempio, se il mouse passa il mouse, il sistema continuerà a generare un flusso di WM_MOUSEHOVER messaggi mentre il mouse è fisso. In realtà non vuoi un altro messaggio WM_MOUSEHOVER finché il mouse non si sposta in un altro punto e passa di nuovo il mouse.

Ecco una piccola classe helper che è possibile usare per gestire gli eventi di rilevamento del mouse.

class MouseTrackEvents
{
    bool m_bMouseTracking;

public:
    MouseTrackEvents() : m_bMouseTracking(false)
    {
    }
    
    void OnMouseMove(HWND hwnd)
    {
        if (!m_bMouseTracking)
        {
            // Enable mouse tracking.
            TRACKMOUSEEVENT tme;
            tme.cbSize = sizeof(tme);
            tme.hwndTrack = hwnd;
            tme.dwFlags = TME_HOVER | TME_LEAVE;
            tme.dwHoverTime = HOVER_DEFAULT;
            TrackMouseEvent(&tme);
            m_bMouseTracking = true;
        }
    }
    void Reset(HWND hwnd)
    {
        m_bMouseTracking = false;
    }
};

Nell'esempio seguente viene illustrato come usare questa classe nella routine della finestra.

LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_MOUSEMOVE:
        mouseTrack.OnMouseMove(m_hwnd);  // Start tracking.

        // TODO: Handle the mouse-move message.

        return 0;

    case WM_MOUSELEAVE:

        // TODO: Handle the mouse-leave message.

        mouseTrack.Reset(m_hwnd);
        return 0;

    case WM_MOUSEHOVER:

        // TODO: Handle the mouse-hover message.

        mouseTrack.Reset(m_hwnd);
        return 0;

    }
    return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}

Gli eventi di rilevamento del mouse richiedono un'ulteriore elaborazione da parte del sistema, quindi lasciarli disabilitati se non sono necessari.

Per completezza, ecco una funzione che esegue una query sul sistema per il timeout predefinito del passaggio del mouse.

UINT GetMouseHoverTime()
{
    UINT msec; 
    if (SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &msec, 0))
    {   
        return msec;
    }
    else
    {
        return 0;
    }
}

Rotellina del mouse

La funzione seguente controlla se è presente una rotellina del mouse.

BOOL IsMouseWheelPresent()
{
    return (GetSystemMetrics(SM_MOUSEWHEELPRESENT) != 0);
}

Se l'utente ruota la rotellina del mouse, la finestra con stato attivo riceve un messaggio di WM_MOUSEWHEEL . Il parametro wParam di questo messaggio contiene un valore intero denominato delta che misura la distanza di rotazione della rotellina. Il delta usa unità arbitrarie, dove 120 unità è definita come rotazione necessaria per eseguire un'azione. Naturalmente, la definizione di un'azione dipende dal programma. Ad esempio, se la rotellina del mouse viene usata per scorrere il testo, ogni 120 unità di rotazione scorre una riga di testo.

Il segno del delta indica la direzione di rotazione:

  • Positivo: ruotare in avanti, lontano dall'utente.
  • Negativo: ruotare indietro, verso l'utente.

Il valore del delta viene inserito in wParam insieme ad alcuni flag aggiuntivi. Utilizzare la macro GET_WHEEL_DELTA_WPARAM per ottenere il valore del delta.

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

Se la rotellina del mouse ha una risoluzione elevata, il valore assoluto del delta potrebbe essere minore di 120. In tal caso, se è opportuno che l'azione venga eseguita in incrementi più piccoli, è possibile farlo. Ad esempio, il testo può scorrere per incrementi di meno di una riga. In caso contrario, accumulare il delta totale fino a quando la ruota ruota abbastanza per eseguire l'azione. Archiviare il delta inutilizzato in una variabile e quando si accumulano 120 unità (positivo o negativo), eseguire l'azione.

Prossima

Input da tastiera