Compartir a través de


Varias operaciones del mouse

En las secciones anteriores se han analizado los clics del mouse y el movimiento del mouse. Estas son algunas otras operaciones que se pueden realizar con el mouse.

Arrastrar elementos de la interfaz de usuario

Si la interfaz de usuario admite el arrastre de elementos de la interfaz de usuario, hay otra función a la que debe llamar en el controlador de mensajes del mouse hacia abajo: DragDetect. La función DragDetect devuelve TRUE si el usuario inicia un gesto del mouse que se debe interpretar como arrastrar. En el código siguiente se muestra cómo usar esta función.

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

Esta es la idea: Cuando un programa admite arrastrar y soltar, no quiere que todos los clics del mouse se interpreten como arrastrar. De lo contrario, el usuario podría arrastrar accidentalmente algo cuando simplemente quería hacer clic en él (por ejemplo, para seleccionarlo). Pero si un mouse es especialmente sensible, puede ser difícil mantener el mouse perfectamente al hacer clic. Por lo tanto, Windows define un umbral de arrastre de unos pocos píxeles. Cuando el usuario presiona el botón del mouse, no se considera un arrastre a menos que el mouse cruce este umbral. La función DragDetect comprueba si se alcanza este umbral. Si la función devuelve TRUE, puede interpretar el clic del mouse como arrastrar. De lo contrario, no.

Nota

Si DragDetect devuelve FALSE, Windows suprime el mensaje WM_LBUTTONUP cuando el usuario suelta el botón del mouse. Por lo tanto, no llame a DragDetect a menos que el programa esté actualmente en un modo que admita arrastrar. (Por ejemplo, si ya está seleccionado un elemento de interfaz de usuario arrastrable). Al final de este módulo, veremos un ejemplo de código más largo que usa la función DragDetect .

 

Confining the Cursor

A veces, es posible que desee restringir el cursor al área cliente o a una parte del área cliente. La función ClipCursor restringe el movimiento del cursor a un rectángulo especificado. Este rectángulo se asigna en coordenadas de pantalla, en lugar de coordenadas de cliente, por lo que el punto (0, 0) significa la esquina superior izquierda de la pantalla. Para traducir las coordenadas de cliente en coordenadas de pantalla, llame a la función ClientToScreen.

El código siguiente limita el cursor al área cliente de la ventana.

    // 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 toma una estructura RECT , pero ClientToScreen toma una estructura POINT . Un rectángulo se define mediante sus puntos superior izquierdo e inferior derecho. Puede limitar el cursor a cualquier área rectangular, incluidas las áreas fuera de la ventana, pero la confinación del cursor al área cliente es una manera típica de usar la función. La confinación del cursor a una región completamente fuera de la ventana sería inusual y los usuarios probablemente lo percibirían como un error.

Para quitar la restricción, llame a ClipCursor con el valor NULL.

ClipCursor(NULL);

Eventos de seguimiento del mouse: mantener el puntero y salir

Otros dos mensajes del mouse están deshabilitados de forma predeterminada, pero pueden ser útiles para algunas aplicaciones:

  • WM_MOUSEHOVER: el cursor se ha desplazado sobre el área cliente durante un período fijo de tiempo.
  • WM_MOUSELEAVE: el cursor ha dejado el área cliente.

Para habilitar estos mensajes, llame a la función TrackMouseEvent .

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

La estructura TRACKMOUSEEVENT contiene los parámetros de la función . El miembro dwFlags de la estructura contiene marcas de bits que especifican los mensajes de seguimiento que le interesan. Puede elegir obtener tanto WM_MOUSEHOVER como WM_MOUSELEAVE, como se muestra aquí, o solo uno de los dos. El miembro dwHoverTime especifica cuánto tiempo debe mantener el puntero el mouse antes de que el sistema genere un mensaje de desplazamiento. Este valor se asigna en milisegundos. La constante HOVER_DEFAULT significa usar el valor predeterminado del sistema.

Después de obtener uno de los mensajes solicitados, se restablece la función TrackMouseEvent . Debe llamarlo de nuevo para obtener otro mensaje de seguimiento. Sin embargo, debe esperar hasta el siguiente mensaje de movimiento del mouse antes de llamar a TrackMouseEvent de nuevo. De lo contrario, la ventana podría estar inundada con mensajes de seguimiento. Por ejemplo, si el mouse mantiene el puntero, el sistema seguirá generando una secuencia de mensajes de WM_MOUSEHOVER mientras el mouse está estacionado. En realidad no quieres otro mensaje de WM_MOUSEHOVER hasta que el mouse se mueva a otro lugar y mantenga el puntero de nuevo.

Esta es una pequeña clase auxiliar que puede usar para administrar eventos de seguimiento 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;
    }
};

En el ejemplo siguiente se muestra cómo usar esta clase en el procedimiento de ventana.

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

Los eventos de seguimiento del mouse requieren un procesamiento adicional por parte del sistema, así que déjelos deshabilitados si no los necesita.

Por integridad, esta es una función que consulta el sistema para el tiempo de espera de desplazamiento predeterminado.

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

Rueda del mouse

La siguiente función comprueba si hay una rueda del mouse presente.

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

Si el usuario gira la rueda del mouse, la ventana con el foco recibe un mensaje WM_MOUSEWHEEL . El parámetro wParam de este mensaje contiene un valor entero denominado delta que mide hasta dónde se gira la rueda. La diferencia usa unidades arbitrarias, donde 120 unidades se define como la rotación necesaria para realizar una "acción". Por supuesto, la definición de una acción depende del programa. Por ejemplo, si la rueda del mouse se usa para desplazar el texto, cada 120 unidades de rotación desplazaría una línea de texto.

El signo de la diferencia indica la dirección de rotación:

  • Positivo: gire hacia delante, lejos del usuario.
  • Negativo: gire hacia atrás, hacia el usuario.

El valor de delta se coloca en wParam junto con algunas marcas adicionales. Use la macro GET_WHEEL_DELTA_WPARAM para obtener el valor de delta.

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

Si la rueda del mouse tiene una alta resolución, el valor absoluto del delta puede ser inferior a 120. En ese caso, si tiene sentido que la acción se produzca en incrementos más pequeños, puede hacerlo. Por ejemplo, el texto podría desplazarse por incrementos de menos de una línea. De lo contrario, acumula el delta total hasta que la rueda gira lo suficiente para realizar la acción. Almacene la diferencia no usada en una variable y, cuando se acumulan 120 unidades (positivas o negativas), realice la acción.

Siguientes

Entrada de teclado