Delen via


Diverse muisbewerkingen

In de vorige secties zijn muisklikken en muisbewegingen besproken. Hier volgen enkele andere bewerkingen die met de muis kunnen worden uitgevoerd.

Ui-elementen slepen

Als uw gebruikersinterface ondersteuning biedt voor het slepen van UI-elementen, is er een andere functie die u moet aanroepen in de berichthandler met de muis: DragDetect. De functie DragDetect retourneert TRUE- als de gebruiker een muisbeweging initieert die moet worden geïnterpreteerd als slepen. De volgende code laat zien hoe u deze functie gebruikt.

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

Dit is het idee: wanneer een programma slepen en neerzetten ondersteunt, wilt u niet dat elke muisklik wordt geïnterpreteerd als slepen. Anders kan de gebruiker per ongeluk iets slepen wanneer hij of zij erop wil klikken (bijvoorbeeld om deze te selecteren). Maar als een muis bijzonder gevoelig is, kan het lastig zijn om de muis perfect stil te houden terwijl u klikt. Daarom definieert Windows een drempelwaarde voor slepen van een paar pixels. Wanneer de gebruiker op de muisknop drukt, wordt deze niet beschouwd als slepen, tenzij de muis deze drempelwaarde overschrijdt. De functie DragDetect test of deze drempelwaarde is bereikt. Als de functie TRUEretourneert, kunt u de muisklik interpreteren als slepen. Anders niet.

Notitie

Als DragDetect-FALSEretourneert, onderdrukt Windows het WM_LBUTTONUP bericht wanneer de gebruiker de muisknop loslaat. Roep daarom DragDetect- niet aan, tenzij uw programma zich momenteel in een modus bevindt die slepen ondersteunt. (Als er bijvoorbeeld al een slepenbaar UI-element is geselecteerd.) Aan het einde van deze module zien we een langer codevoorbeeld dat gebruikmaakt van de functie DragDetect.

 

De cursor in beslag nemen

Soms wilt u de cursor beperken tot het clientgebied of een deel van het clientgebied. De functie ClipCursor beperkt de verplaatsing van de cursor tot een opgegeven rechthoek. Deze rechthoek wordt gegeven in schermcoördinaten in plaats van clientcoördinaten, dus het punt (0, 0) betekent de linkerbovenhoek van het scherm. Als u clientcoördinaten wilt vertalen naar schermcoördinaten, roept u de functie aan ClientToScreen-.

De volgende code beperkt de cursor tot het clientgebied van het venster.

    // 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 een RECT--structuur gebruikt, maar ClientToScreen een POINT structuur. Een rechthoek wordt gedefinieerd door de punten linksboven en rechtsonder. U kunt de cursor beperken tot een rechthoekig gebied, inclusief gebieden buiten het venster, maar het insluiten van de cursor in het clientgebied is een typische manier om de functie te gebruiken. Als u de cursor volledig buiten uw venster in een regio in beslag neemt, zou dit ongebruikelijk zijn en zouden gebruikers deze waarschijnlijk als een bug ervaren.

Als u de beperking wilt verwijderen, roept u ClipCursor- aan met de waarde NULL-.

ClipCursor(NULL);

Gebeurtenissen voor het bijhouden van de muis: aanwijzen en verlaten

Twee andere muisberichten zijn standaard uitgeschakeld, maar kunnen handig zijn voor sommige toepassingen:

  • WM_MOUSEHOVER: de cursor heeft gedurende een bepaalde periode de muisaanwijzer over het clientgebied geplaatst.
  • WM_MOUSELEAVE: de cursor heeft het clientgebied verlaten.

Als u deze berichten wilt inschakelen, roept u de functie TrackMouseEvent aan.

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

De TRACKMOUSEEVENT structuur bevat de parameters voor de functie. De dwFlags lid van de structuur bevat bitvlagken die aangeven in welke traceringsberichten u geïnteresseerd bent. U kunt ervoor kiezen om zowel WM_MOUSEHOVER als WM_MOUSELEAVEte krijgen, zoals hier wordt weergegeven, of slechts één van de twee. De dwHoverTime lid geeft aan hoe lang de muis moet bewegen voordat het systeem een aanwijsbericht genereert. Deze waarde wordt uitgedrukt in milliseconden. De constante HOVER_DEFAULT betekent dat de systeemstandaard moet worden gebruikt.

Nadat u een van de door u aangevraagde berichten hebt ontvangen, wordt de functie TrackMouseEvent opnieuw ingesteld. U moet het opnieuw aanroepen om een ander traceringsbericht op te halen. U moet echter wachten totdat het volgende bericht met de muisaanwijzer wordt verplaatst voordat u TrackMouseEvent opnieuw aanroept. Anders kan uw venster worden overspoeld met traceringsberichten. Als de muis bijvoorbeeld aanwijst, blijft het systeem een stroom van WM_MOUSEHOVER berichten genereren terwijl de muis stilstaat. U wilt niet echt nog een WM_MOUSEHOVER bericht totdat de muis naar een andere plek wordt verplaatst en de muisaanwijzers weer aanwijst.

Hier volgt een kleine helperklasse die u kunt gebruiken om gebeurtenissen voor het bijhouden van muis te beheren.

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

In het volgende voorbeeld ziet u hoe u deze klasse gebruikt in uw vensterprocedure.

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

Voor het bijhouden van muisgebeurtenissen is extra verwerking door het systeem vereist. Laat ze dus uitgeschakeld als u ze niet nodig hebt.

Voor volledigheid is hier een functie die het systeem opvraagt voor de standaard time-out voor aanwijzen.

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

Muiswiel

Met de volgende functie wordt gecontroleerd of er een muiswiel aanwezig is.

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

Als de gebruiker het muiswiel draait, ontvangt het venster met de focus een WM_MOUSEWHEEL bericht. De parameter wParam van dit bericht bevat een geheel getal dat de delta- wordt genoemd waarmee wordt gemeten hoe ver het wiel is gedraaid. De delta maakt gebruik van willekeurige eenheden, waarbij 120 eenheden worden gedefinieerd als de rotatie die nodig is om één actie uit te voeren. Natuurlijk is de definitie van een actie afhankelijk van uw programma. Als het muiswiel bijvoorbeeld wordt gebruikt om tekst te schuiven, schuift elke 120 eenheden rotatie één regel tekst.

Het teken van de delta geeft de draairichting aan:

  • Positief: Vooruit draaien, weg van de gebruiker.
  • Negatief: Draai achteruit naar de gebruiker.

De waarde van de delta wordt in wParam geplaatst, samen met enkele extra vlaggen. Gebruik de GET_WHEEL_DELTA_WPARAM macro om de waarde van de delta op te halen.

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

Als het muiswiel een hoge resolutie heeft, is de absolute waarde van de delta mogelijk kleiner dan 120. In dat geval kunt u dit doen als het zinvol is om de actie in kleinere stappen uit te voeren. Tekst kan bijvoorbeeld schuiven met stappen van minder dan één regel. Anders verzamelt u de totale delta totdat het wiel voldoende draait om de actie uit te voeren. Sla de ongebruikte delta op in een variabele en voer de actie uit wanneer 120 eenheden worden verzameld (positief of negatief).

Volgend

toetsenbordinvoer