共用方式為


其他滑鼠作業

前幾節已討論滑鼠點擊和滑鼠移動。 以下是一些可以使用滑鼠執行的其他作業。

拖曳 UI 元素

如果您的 UI 支援拖曳 UI 元素,您應該在滑鼠向下訊息處理常式中呼叫其他函式: DragDetect。 如果使用者起始應該解譯為拖曳的滑鼠手勢, DragDetect 函式會傳回 TRUE 。 下列程式碼示範如何使用此函式。

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

以下是概念:當程式支援拖放時,您不希望每個滑鼠按一下都解譯為拖曳。 否則,當使用者只是想要按一下它 (時,使用者可能會不小心拖曳某個專案,以選取它) 。 但是,如果滑鼠特別敏感,按一下滑鼠時可能很難讓滑鼠保持完美。 因此,Windows 會定義數個圖元的拖曳閾值。 當使用者按下滑鼠按鍵時,除非滑鼠超過此閾值,否則不會被視為拖曳。 DragDetect函式會測試是否已達到此臨界值。 如果函式傳回 TRUE,您可以將滑鼠按一下解譯為拖曳。 否則,請勿。

注意

如果 DragDetect 傳回 FALSE,當使用者放開滑鼠按鍵時,Windows 會隱藏 WM_LBUTTONUP 訊息。 因此,除非您的程式目前處於支援拖曳的模式,否則請勿呼叫 DragDetect 。 (例如,如果已選取可拖曳的 UI 元素。) 在本課程模組結束時,我們將會看到使用 DragDetect 函式的較長程式碼範例。

 

限制游標

有時候,您可能想要將游標限制在工作區或工作區的一部分。 ClipCursor函式會將游標的移動限制為指定的矩形。 此矩形是以螢幕座標提供,而不是用戶端座標,因此點 (0,0) 表示螢幕左上角。 若要將用戶端座標轉譯成螢幕座標,請呼叫 函式 ClientToScreen

下列程式碼會將游標限制在視窗的工作區。

    // 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 會採用 RECT 結構,但 ClientToScreen 會採用 POINT 結構。 矩形是由其左上方和右下角點所定義。 您可以將游標限制在任何矩形區域,包括視窗外的區域,但將游標限制在工作區是使用函式的一般方式。 將游標限制在視窗外的整個區域是不尋常的,而且使用者可能會將其視為 Bug。

若要移除限制,請使用Null值呼叫ClipCursor

ClipCursor(NULL);

滑鼠追蹤事件:暫留和離開

預設會停用其他兩個滑鼠訊息,但對某些應用程式可能很有用:

若要啟用這些訊息,請呼叫 TrackMouseEvent 函式。

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

TRACKMOUSEEVENT結構包含函式的參數。 結構的 dwFlags 成員包含位旗標,指定您感興趣的追蹤訊息。 您可以選擇同時取得 WM_MOUSEHOVERWM_MOUSELEAVE,如下所示,或只取得兩者之一。 dwHoverTime成員會指定滑鼠在系統產生暫留訊息之前需要暫留的時間長度。 這個值是以毫秒為單位來指定。 常數 HOVER_DEFAULT 表示使用系統預設值。

取得您要求的其中一個訊息之後, TrackMouseEvent 函式就會重設。 您必須再次呼叫它,才能取得另一個追蹤訊息。 不過,您應該等到下一個滑鼠移動訊息,再再次呼叫 TrackMouseEvent 。 否則,您的視窗可能會被追蹤訊息填滿。 例如,如果滑鼠暫留,系統會在滑鼠靜止時繼續產生 WM_MOUSEHOVER 訊息的資料流程。 您實際上不會想要另一個 WM_MOUSEHOVER 訊息,直到滑鼠移至另一個位置並再次暫留為止。

以下是可用來管理滑鼠追蹤事件的小型協助程式類別。

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

下一個範例示範如何在視窗程式中使用此類別。

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

滑鼠追蹤事件需要系統的額外處理,因此如果您不需要它們,請將其停用。

為了完整起見,以下是查詢系統的預設暫留逾時函式。

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

滑鼠滾輪

下列函式會檢查滑鼠滾輪是否存在。

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

如果使用者旋轉滑鼠滾輪,具有焦點的視窗會收到 WM_MOUSEWHEEL 訊息。 此訊息的 wParam 參數包含一個整數值,稱為 差異 ,可測量滾輪旋轉的距離。 差異會使用任意單位,其中 120 個單位定義為執行一個「動作」所需的旋轉。當然,動作的定義取決於您的程式。 例如,如果使用滑鼠滾輪來捲動文字,則每 120 個旋轉單位都會捲動一行文字。

差異的正負號表示旋轉方向:

  • 正數:向前旋轉,離開使用者。
  • 負數:向後旋轉,向使用者旋轉。

差異的值會放在 wParam 中,以及一些額外的旗標。 使用 GET_WHEEL_DELTA_WPARAM 宏來取得差異的值。

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

如果滑鼠滾輪具有高解析度,差異的絕對值可能小於 120。 在此情況下,如果動作的增量較小,您可以這麼做。 例如,文字可能會以小於一行的遞增捲動。 否則,請累積總差異,直到滾輪旋轉足以執行動作為止。 將未使用的差異儲存在變數中,當 120 單位累積 (正數或負數) 時,請執行動作。

下一個

鍵盤輸入