Partager via


Opérations diverses de la souris

Les sections précédentes ont abordé les clics de souris et le mouvement de la souris. Voici d’autres opérations qui peuvent être effectuées avec la souris.

Glisser des éléments d’interface utilisateur

Si votre interface utilisateur prend en charge le glissement des éléments de l’interface utilisateur, il existe une autre fonction que vous devez appeler dans votre gestionnaire de messages vers le bas de la souris : DragDetect. La fonction DragDetect retourne TRUE si l’utilisateur lance un mouvement de souris qui doit être interprété comme faisant glisser. Le code suivant montre comment utiliser cette fonction.

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

Voici l’idée : lorsqu’un programme prend en charge le glisser-déplacer, vous ne souhaitez pas que chaque clic de souris soit interprété comme un glisser-déplacer. Sinon, l’utilisateur peut glisser accidentellement quelque chose lorsqu’il a simplement voulu cliquer dessus (par exemple, pour le sélectionner). Mais si une souris est particulièrement sensible, il peut être difficile de garder la souris parfaitement tout en cliquant. Par conséquent, Windows définit un seuil de glissement de quelques pixels. Lorsque l’utilisateur appuie sur le bouton de la souris, il n’est pas considéré comme un glissement, sauf si la souris franchit ce seuil. La fonction DragDetect teste si ce seuil est atteint. Si la fonction retourne TRUE, vous pouvez interpréter le clic de la souris en tant que glisser-déplacer. Sinon, ne le faites pas.

Note

Si dragDetect retourne FAUX, Windows supprime le message WM_LBUTTONUP lorsque l’utilisateur relâche le bouton de la souris. Par conséquent, n’appelez pas DragDetect, sauf si votre programme est actuellement en mode prenant en charge le glissement. (Par exemple, si un élément d’interface utilisateur draggable est déjà sélectionné.) À la fin de ce module, nous verrons un exemple de code plus long qui utilise la fonction DragDetect.

 

Confisage du curseur

Parfois, vous souhaiterez peut-être restreindre le curseur à la zone cliente ou une partie de la zone cliente. La fonctionClipCursorlimite le mouvement du curseur à un rectangle spécifié. Ce rectangle est donné dans les coordonnées de l’écran, plutôt que les coordonnées du client, de sorte que le point (0, 0) signifie le coin supérieur gauche de l’écran. Pour traduire les coordonnées du client en coordonnées d’écran, appelez la fonction ClientToScreen.

Le code suivant limite le curseur à la zone cliente de la fenêtre.

    // 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 prend une structure RECT, mais ClientToScreen prend une structure POINT. Un rectangle est défini par ses points supérieur gauche et inférieur droit. Vous pouvez limiter le curseur à n’importe quelle zone rectangulaire, y compris les zones situées en dehors de la fenêtre, mais la confision du curseur à la zone cliente est un moyen typique d’utiliser la fonction. Le fait de confiser le curseur à une région entièrement en dehors de votre fenêtre serait inhabituel, et les utilisateurs le considèrent probablement comme un bogue.

Pour supprimer la restriction, appelez ClipCursor avec la valeur NULL.

ClipCursor(NULL);

Événements de suivi de la souris : pointer et quitter

Deux autres messages de souris sont désactivés par défaut, mais peuvent être utiles pour certaines applications :

Pour activer ces messages, appelez la fonctionTrackMouseEvent.

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

La structure TRACKMOUSEEVENT contient les paramètres de la fonction. Le dwFlags membre de la structure contient des indicateurs de bits qui spécifient les messages de suivi qui vous intéressent. Vous pouvez choisir d’obtenir à la fois WM_MOUSEHOVER et WM_MOUSELEAVE, comme indiqué ici, ou simplement l’un des deux. Le membre dwHoverTime spécifie la durée pendant laquelle la souris doit pointer avant que le système génère un message de pointage. Cette valeur est donnée en millisecondes. La constante HOVER_DEFAULT signifie utiliser la valeur par défaut du système.

Une fois que vous avez obtenu l’un des messages que vous avez demandés, la fonction TrackMouseEvent réinitialise. Vous devez l’appeler de nouveau pour obtenir un autre message de suivi. Toutefois, vous devez attendre le prochain message de déplacement de la souris avant d’appeler TrackMouseEvent. Sinon, votre fenêtre peut être inondée de messages de suivi. Par exemple, si la souris pointe, le système continue à générer un flux de messages WM_MOUSEHOVER pendant que la souris est stationnaire. Vous ne voulez pas réellement un autre message WM_MOUSEHOVER tant que la souris n’est pas déplacée vers un autre endroit et pointe à nouveau.

Voici une petite classe d’assistance que vous pouvez utiliser pour gérer les événements de suivi de la souris.

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;
    }
};

L’exemple suivant montre comment utiliser cette classe dans votre procédure de fenêtre.

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);
}

Les événements de suivi de la souris nécessitent un traitement supplémentaire par le système, donc laissez-les désactivés si vous n’en avez pas besoin.

Pour l’exhaustivité, voici une fonction qui interroge le système pour le délai d’attente de pointage par défaut.

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

Roulette de la souris

La fonction suivante vérifie si une roulette de souris est présente.

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

Si l’utilisateur fait pivoter la roulette de la souris, la fenêtre avec focus reçoit un message WM_MOUSEWHEEL. Le paramètre wParam de ce message contient une valeur entière appelée delta qui mesure la distance de rotation de la roue. Le delta utilise des unités arbitraires, où 120 unités sont définies comme la rotation nécessaire pour effectuer une « action ». Bien sûr, la définition d’une action dépend de votre programme. Par exemple, si la roulette de la souris est utilisée pour faire défiler le texte, chaque 120 unités de rotation fait défiler une ligne de texte.

Le signe du delta indique la direction de rotation :

  • Positif : faire pivoter vers l’avant, loin de l’utilisateur.
  • Négatif : faire pivoter vers l’arrière vers l’utilisateur.

La valeur du delta est placée dans wParam, ainsi que d’autres indicateurs. Utilisez la macro GET_WHEEL_DELTA_WPARAM pour obtenir la valeur du delta.

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

Si la roulette de la souris a une haute résolution, la valeur absolue du delta peut être inférieure à 120. Dans ce cas, s’il est judicieux que l’action se produise par incréments plus petits, vous pouvez le faire. Par exemple, le texte peut faire défiler par incréments de moins d’une ligne. Sinon, accumulez le delta total jusqu’à ce que la roue pivote suffisamment pour effectuer l’action. Stockez le delta inutilisé dans une variable et lorsque 120 unités s’accumulent (positives ou négatives), effectuez l’action.

Prochain

d’entrée clavier