Sdílet prostřednictvím


Různé operace myši

V předchozích částech jsme probírali kliknutí myší a pohyb myši. Tady jsou některé další operace, které lze provést pomocí myši.

Přetažení prvků uživatelského rozhraní

Pokud vaše uživatelské rozhraní podporuje přetahování prvků uživatelského rozhraní, existuje jedna další funkce, kterou byste měli volat v obslužné rutině zprávy myši: DragDetect. Funkce DragDetect vrátí TRUE, pokud uživatel zahájí gesto myši, které by mělo být interpretováno jako přetahování. Následující kód ukazuje, jak tuto funkci používat.

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

Tady je myšlenka: Pokud program podporuje přetažení, nechcete, aby každé kliknutí myší bylo interpretováno jako přetažení. Jinak může uživatel něco omylem přetáhnout, když na něj jednoduše chce kliknout (například ho vybrat). Ale pokud je myš obzvláště citlivá, může být obtížné udržet myš dokonale i při kliknutí. Systém Windows proto definuje prahovou hodnotu přetažení několika pixelů. Když uživatel stiskne tlačítko myši, nepovažuje se za přetažení, pokud myš překročí tuto prahovou hodnotu. Funkce DragDetect testuje, zda je tato prahová hodnota dosažena. Pokud funkce vrátí true, můžete kliknutí myší interpretovat jako přetažení. V opačném případě ne.

Poznámka

Pokud dragDetect vrátí FALSE, Systém Windows potlačí WM_LBUTTONUP zprávu, když uživatel uvolní tlačítko myši. Proto nevolejte DragDetect, pokud váš program není aktuálně v režimu, který podporuje přetahování. (Pokud je například již vybrán přetahovatelný prvek uživatelského rozhraní.) Na konci tohoto modulu uvidíme delší příklad kódu, který používá funkci DragDetect.

 

Konfigurace kurzoru

Někdy můžete chtít omezit kurzor na klientskou oblast nebo část klientské oblasti. Funkce ClipCursor omezuje pohyb kurzoru na zadaný obdélník. Tento obdélník je uveden v souřadnicích obrazovky, nikoli v souřadnicích klienta, takže bod (0, 0) znamená levý horní roh obrazovky. Chcete-li přeložit souřadnice klienta na souřadnice obrazovky, zavolejte funkci ClientToScreen.

Následující kód omezuje kurzor na klientskou oblast okna.

    // 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 přebírástrukturuRECT, ale ClientToScreen přebírá strukturu POINT. Obdélník je definován v levém horním a pravém dolním rohu. Kurzor můžete omezit na libovolnou obdélníkovou oblast, včetně oblastí mimo okno, ale umístění kurzoru do klientské oblasti představuje typický způsob použití funkce. Spojení kurzoru do oblasti zcela mimo okno by bylo neobvyklé a uživatelé by ho pravděpodobně vnímali jako chybu.

Chcete-li omezení odebrat, zavolejte ClipCursor s hodnotou NULL.

ClipCursor(NULL);

Události sledování myši: Najetí myší a opuštění

Ve výchozím nastavení jsou zakázány dvě další zprávy myši, ale mohou být užitečné pro některé aplikace:

Pokud chcete tyto zprávy povolit, zavolejte funkci TrackMouseEvent.

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

Struktura TRACKMOUSEEVENT obsahuje parametry funkce. dwFlags člen struktury obsahuje bitové příznaky, které určují, které sledovací zprávy vás zajímají. Můžete se rozhodnout získat WM_MOUSEHOVER i WM_MOUSELEAVE, jak je znázorněno zde, nebo jen jeden z těchto dvou. Člen dwHoverTime určuje, jak dlouho musí myš najet myší, než systém vygeneruje zprávu přechodu myší. Tato hodnota je uvedena v milisekundách. Konstanta HOVER_DEFAULT znamená použít výchozí systém.

Po získání jedné z požadovaných zpráv se funkce TrackMouseEvent resetuje. Pokud chcete získat další zprávu sledování, musíte ji znovu zavolat. Před opětovným voláním TrackMouseE vent byste ale měli počkat na další zprávu přesunutí myší. Jinak může být okno zahlceno sledováním zpráv. Pokud například myš najet myší, systém bude dál generovat datový proud WM_MOUSEHOVER zpráv, zatímco myš je stabilní. Ve skutečnosti nechcete, aby se další WM_MOUSEHOVER zpráva, dokud se myš nepřesune na jiné místo a znovu najede myší.

Tady je malá pomocná třída, kterou můžete použít ke správě událostí sledování myši.

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

Další příklad ukazuje, jak tuto třídu použít v postupu okna.

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

Události sledování myši vyžadují další zpracování systémem, takže pokud je nepotřebujete, nechte je zakázané.

Pro úplnost zde je funkce, která dotazuje systém na výchozí časový limit přechodu myší.

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

Kolečko myši

Následující funkce zkontroluje, jestli je k dispozici kolečko myši.

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

Pokud uživatel otočí kolečko myši, okno s fokusem obdrží WM_MOUSEWHEEL zprávu. Parametr wParam této zprávy obsahuje celočíselnou hodnotu s názvem delta, která měří, jak daleko bylo kolo otočené. Rozdíl používá libovolné jednotky, kde je definováno 120 jednotek jako rotace potřebná k provedení jedné "akce". Definice akce samozřejmě závisí na vašem programu. Pokud se například kolečko myši používá k posouvání textu, posune se každý 120 jednotek otáčení o jeden řádek textu.

Znaménko rozdílu označuje směr otáčení:

  • Pozitivní: Otočit dopředu, pryč od uživatele.
  • Záporné: Otočte směrem k uživateli směrem dozadu.

Hodnota rozdílu je umístěna v wParam spolu s některými dalšími příznaky. K získání hodnoty rozdílu použijte makro GET_WHEEL_DELTA_WPARAM.

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

Pokud má kolečko myši vysoké rozlišení, může být absolutní hodnota rozdílu menší než 120. Pokud v takovém případě dává smysl, aby akce probíhala v menších přírůstcích, můžete to udělat. Text se například může posouvat o více než jeden řádek. Jinak se shromáždí celková rozdílová hodnota, dokud kolečko dostatečně neotáčí k provedení akce. Uložte nepoužívaný rozdíl v proměnné a při kumulování 120 jednotek (kladné nebo záporné) proveďte akci.

Další

vstupu klávesnice