滑鼠輸入概觀

滑鼠是應用程式的重要但選擇性使用者輸入裝置。 撰寫良好的應用程式應該包含滑鼠介面,但不應該只依賴滑鼠來取得使用者輸入。 應用程式也應該提供完整的鍵盤支援。

應用程式會以傳送或張貼至視窗的訊息形式接收滑鼠輸入。

本節包含下列主題:

滑鼠游標

當使用者移動滑鼠時,系統會在稱為 滑鼠游標的畫面上移動點陣圖。 滑鼠游標包含稱為 作用點的單一圖元點,這是系統追蹤並辨識為游標位置的點。 發生滑鼠事件時,包含作用點的視窗通常會接收事件所產生的滑鼠訊息。 視窗不需要使用中,或具有鍵盤焦點才能接收滑鼠訊息。

系統會維護可控制滑鼠速度的變數,也就是當使用者移動滑鼠時游標移動的距離。 您可以使用 SystemParametersInfo 函式搭配 SPI_GETMOUSESPI_SETMOUSE 旗標來擷取或設定滑鼠速度。 如需滑鼠游標的詳細資訊,請參閱 資料指標

滑鼠捕捉

當發生滑鼠事件時,系統通常會將滑鼠訊息張貼到包含游標作用點的視窗。 應用程式可以使用 SetCapture 函式將滑鼠訊息路由傳送至特定視窗,來變更此行為。 視窗會接收所有滑鼠訊息,直到應用程式呼叫 ReleaseCapture 函式或指定另一個擷取視窗,或直到使用者按一下由另一個執行緒建立的視窗為止。

當滑鼠擷取變更時,系統會將 WM_CAPTURECHANGED 訊息傳送至遺失滑鼠擷取的視窗。 訊息的 lParam 參數會指定取得滑鼠擷取之視窗的控制碼。

只有前景視窗可以擷取滑鼠輸入。 當背景視窗嘗試擷取滑鼠輸入時,它只會接收當游標作用點位於視窗可見部分時所發生的滑鼠事件訊息。

如果視窗必須接收所有滑鼠輸入,即使游標在視窗外移動,擷取滑鼠輸入也很有用。 例如,應用程式通常會追蹤滑鼠按鍵向下事件之後的游標位置,並遵循游標,直到發生滑鼠按鍵向上事件為止。 如果應用程式尚未擷取滑鼠輸入,而且使用者將滑鼠按鍵放開視窗外,視窗就不會收到按鈕向上訊息。

執行緒可以使用 GetCapture 函式來判斷其中一個視窗是否已擷取滑鼠。 如果其中一個執行緒的視窗已擷取滑鼠, GetCapture 會擷取視窗的控制碼。

滑鼠 ClickLock

Mouse ClickLock 協助工具功能可讓使用者在按一下後鎖定主要滑鼠按鍵。 對應用程式,按鈕仍會顯示為按下。 若要解除鎖定按鈕,應用程式可以傳送任何滑鼠訊息,或使用者可以按一下任何滑鼠按鍵。 此功能可讓使用者更輕鬆地進行複雜的滑鼠組合。 例如,具有特定實體限制的使用者可以更輕鬆地反白顯示文字、拖曳物件或開啟功能表。 如需詳細資訊,請參閱 SystemParametersInfo中的下列旗標和:

  • SPI_GETMOUSECLICKLOCK
  • SPI_SETMOUSECLICKLOCK
  • SPI_GETMOUSECLICKLOCKTIME
  • SPI_SETMOUSECLICKLOCKTIME

滑鼠設定

雖然滑鼠是應用程式的重要輸入裝置,但並非所有使用者都必須有滑鼠。 應用程式可以將 SM_MOUSEPRESENT 值傳遞至 GetSystemMetrics 函式,以判斷系統是否包含滑鼠。

Windows 支援最多三個按鈕的滑鼠。 在三鍵滑鼠上,按鈕會指定為左、中間和右按鈕。 與滑鼠按鍵相關的訊息和具名常數會使用字母 L、M 和 R 來識別按鈕。 單一按鈕滑鼠上的按鈕會被視為左按鈕。 雖然 Windows 支援具有多個按鈕的滑鼠,但大部分的應用程式主要會使用左按鈕,而其他應用程式則完全不使用。

應用程式也可以支援滑鼠滾輪。 滑鼠滾輪可以按下或旋轉。 按下滑鼠滾輪時,它會作為中間 (第三個) 按鈕,將一般中間按鈕訊息傳送至您的應用程式。 旋轉時,滾輪訊息會傳送至您的應用程式。 如需詳細資訊,請參閱 滑鼠滾輪 一節。

應用程式可以支援應用程式命令按鈕。 這些按鈕稱為 X 按鈕的設計目的是為了方便存取網際網路瀏覽器、電子郵件和媒體服務。 按下 X 按鈕時, 會將WM_APPCOMMAND 訊息傳送至您的應用程式。 如需詳細資訊,請參閱 WM_APPCOMMAND 訊息中的描述。

應用程式可以將 SM_CMOUSEBUTTONS 值傳遞至 GetSystemMetrics 函式,以判斷滑鼠上的按鈕數目。 若要為左側使用者設定滑鼠,應用程式可以使用 SwapMouseButton 函式來反轉左右滑鼠按鍵的意義。 將 SPI_SETMOUSEBUTTONSWAP 值傳遞至 SystemParametersInfo 函 式,是反轉按鈕意義的另一種方式。 不過請注意,滑鼠是共用資源,因此反轉按鈕的意義會影響所有應用程式。

XBUTTON

Windows 支援具有五個按鈕的滑鼠。 除了左側、中間和右按鈕之外,還有 XBUTTON1 和 XBUTTON2,可在使用瀏覽器時提供向後和向前流覽。

視窗管理員透過 WM_XBUTTON*WM_NCXBUTTON* 訊息支援 XBUTTON1 和 XBUTTON2。 這些訊息中 WPARAM 的 HIWORD 包含旗標,指出按下了哪個 X 按鈕。 由於這些滑鼠訊息也適用于常數 WM_MOUSEFIRSTWM_MOUSELAST,因此應用程式可以使用 GetMessagePeekMessage篩選所有滑鼠訊息。

下列支援 XBUTTON1 和 XBUTTON2:

下列 API 已修改為支援這些按鈕:

元件應用程式中的子視窗不太可能能夠直接實作 XBUTTON1 和 XBUTTON2 的命令。 因此 DefWindowProc 會在按一下 X 按鈕時,將 WM_APPCOMMAND 訊息傳送至視窗。 DefWindowProc 也會將 WM_APPCOMMAND 訊息傳送至其父視窗。 這類似于以滑鼠右鍵按一下叫用操作功能表的方式,DefWindowProc 會將 WM_CONTEXTMENU 訊息傳送至功能表,並將它傳送至其父系。 此外,如果 DefWindowProc 收到最上層視窗 的WM_APPCOMMAND 訊息,它會使用程式碼HSHELL_APPCOMMAND呼叫殼層勾點。

鍵盤支援瀏覽器功能、媒體功能、應用程式啟動和電源管理的額外按鍵。 如需詳細資訊,請參閱 流覽和其他函式的鍵盤按鍵

滑鼠訊息

當使用者移動滑鼠,或按下或放開滑鼠按鍵時,滑鼠會產生輸入事件。 系統會將滑鼠輸入事件轉換成訊息,並將其張貼至適當的執行緒訊息佇列。 當滑鼠訊息的張貼速度比執行緒快時,系統會捨棄最新的滑鼠訊息以外的所有訊息。

當游標位於視窗的框線內,或視窗已擷取滑鼠時發生滑鼠事件時,視窗會收到滑鼠訊息。 滑鼠訊息分成兩個群組:工作區訊息和非工作區訊息。 一般而言,應用程式會處理工作區訊息,並忽略非工作區訊息。

本節包含下列主題:

工作區滑鼠訊息

當滑鼠事件發生在視窗的工作區內時,視窗會收到工作區滑鼠訊息。 當使用者在工作區內移動游標時,系統會將 WM_MOUSEMOVE 訊息張貼到視窗。 當使用者按下或放開滑鼠按鍵時,游標位於工作區內時,它會張貼下列其中一則訊息。

訊息 意義
WM_LBUTTONDBLCLK 滑鼠左鍵已按兩下。
WM_LBUTTONDOWN 按滑鼠左鍵。
WM_LBUTTONUP 放開滑鼠左鍵。
WM_MBUTTONDBLCLK 按兩下滑鼠中間按鈕。
WM_MBUTTONDOWN 按滑鼠中間鍵。
WM_MBUTTONUP 放開中間滑鼠按鍵。
WM_RBUTTONDBLCLK 按兩下滑鼠右鍵。
WM_RBUTTONDOWN 按滑鼠右鍵。
WM_RBUTTONUP 放開滑鼠右鍵。
WM_XBUTTONDBLCLK 按兩下 X 滑鼠按鍵。
WM_XBUTTONDOWN 按下 X 滑鼠按鍵。
WM_XBUTTONUP 已放開 X 滑鼠按鍵。

 

此外,應用程式可以呼叫 TrackMouseEvent 函式,讓系統傳送其他兩則訊息。 當游標停留在特定時段的工作區上時,它會張貼 WM_MOUSEHOVER 訊息。 當游標離開工作區時,它會張貼 WM_MOUSELEAVE 訊息。

訊息參數

工作區滑鼠訊息的 lParam 參數表示游標作用點的位置。 低序單字表示作用點的 X 座標,而高序單字則表示 Y 座標。 座標是在用戶端座標中指定。 在用戶端座標系統中,會指定畫面上所有點,相對於工作區左上角的座標 (0,0) 。

wParam參數包含旗標,指出滑鼠事件時其他滑鼠按鍵的狀態和 CTRL 和 SHIFT 鍵。 當滑鼠訊息處理取決於另一個滑鼠按鍵或 CTRL 或 SHIFT 鍵的狀態時,您可以檢查這些旗標。 wParam參數可以是下列值的組合。

Description
MK_CONTROL CTRL 鍵已關閉。
MK_LBUTTON 滑鼠左鍵已關閉。
MK_MBUTTON 滑鼠中間鍵已關閉。
MK_RBUTTON 滑鼠右鍵已關閉。
MK_SHIFT SHIFT 鍵已關閉。
MK_XBUTTON1 第一個 X 按鈕已關閉。
MK_XBUTTON2 第二個 X 按鈕已關閉。

 

Double-Click訊息

當使用者連續兩次按一下滑鼠按鍵時,系統會產生按兩下訊息。 當使用者按一下按鈕時,系統會建立以游標作用點為中心的矩形。 它也會標示按一下發生的時間。 當使用者第二次按一下相同的按鈕時,系統會判斷作用點是否仍在矩形內,並計算自第一次按一下後經過的時間。 如果作用點仍在矩形內,且經過的時間未超過按兩下逾時值,系統會產生按兩下訊息。

應用程式可以分別使用 GetDoubleClickTimeSetDoubleClickTime 函式來取得和設定按兩下逾時值。 或者,應用程式可以使用 SPI_SETDOUBLECLICKTIME 旗標搭配 SystemParametersInfo 函式來設定按兩下逾時值。 它也可以設定系統用來偵測按兩下的矩形大小,方法是將 SPI_SETDOUBLECLKWIDTHSPI_SETDOUBLECLKHEIGHT 旗標傳遞至 SystemParametersInfo。 不過請注意,設定按兩下逾時值和矩形會影響所有應用程式。

應用程式定義的視窗預設不會接收按兩下訊息。 由於產生按兩下訊息所涉及的系統額外負荷,這些訊息只會針對屬於具有 CS_DBLCLKS 類別樣式之類別的視窗產生。 註冊視窗類別時,您的應用程式必須設定此樣式。 如需詳細資訊,請參閱 視窗類別

按兩下訊息一律是四個訊息系列中的第三個訊息。 前兩則訊息是第一次按一下所產生的按鈕關閉和按鈕向上訊息。 第二次按一下會產生按兩下訊息,後面接著另一個按鈕訊息。 例如,按兩下滑鼠左鍵會產生下列訊息順序:

  1. WM_LBUTTONDOWN
  2. WM_LBUTTONUP
  3. WM_LBUTTONDBLCLK
  4. WM_LBUTTONUP

因為視窗一律會在收到按兩下訊息之前收到按鈕關閉訊息,所以應用程式通常會使用按兩下訊息來擴充在按鈕關閉訊息期間開始的工作。 例如,當使用者在Microsoft 小畫家的調色盤中按一下色彩時,[繪製] 會顯示調色盤旁的選取色彩。 當使用者按兩下色彩時,[繪製] 會顯示色彩,並開啟 [ 編輯色彩 ] 對話方塊。

非工作區滑鼠訊息

當滑鼠事件發生在工作區以外的任何視窗中時,視窗會收到非工作區滑鼠訊息。 視窗的非工作區包含其框線、功能表列、標題列、捲軸、視窗功能表、最小化按鈕,以及最大化按鈕。

系統主要會產生非工作區訊息以供自己使用。 例如,當游標作用點移至視窗框線時,系統會使用非工作區訊息,將游標變更為雙頭箭號。 視窗必須將非工作區滑鼠訊息傳遞至 DefWindowProc 函式,才能利用內建的滑鼠介面。

每個工作區滑鼠訊息都有對應的非工作區滑鼠訊息。 這些訊息的名稱類似,不同之處在于非工作區訊息的具名常數包含字母 NC。 例如,移動非工作區中的資料指標會產生 WM_NCMOUSEMOVE 訊息,並在游標位於非工作區時按下滑鼠左鍵會產生 WM_NCLBUTTONDOWN 訊息。

非工作區滑鼠訊息的 lParam 參數是一種結構,其中包含游標作用點的 x 和 Y 座標。 不同于工作區滑鼠訊息的座標,座標是在螢幕座標中指定,而不是用戶端座標。 在螢幕座標系統中,畫面上的所有點都相對於畫面左上角的座標 (0,0) 。

wParam參數包含點擊測試值,這個值表示發生滑鼠事件的非工作區中的位置。 下一節說明點擊測試值的目的。

WM_NCHITTEST訊息

每當發生滑鼠事件時,系統會將 WM_NCHITTEST 訊息傳送至包含游標作用點的視窗,或已擷取滑鼠的視窗。 系統會使用此訊息來判斷是否要傳送工作區或非工作區滑鼠訊息。 必須接收滑鼠移動和滑鼠按鍵訊息的應用程式必須將 WM_NCHITTEST 訊息傳遞至 DefWindowProc 函式。

WM_NCHITTEST訊息的lParam參數包含游標作用點的螢幕座標。 DefWindowProc 函式會檢查座標,並傳回點擊測試值,指出作用點的位置。 點擊測試值可以是下列其中一個值。

作用點的位置
HTBORDER 在沒有調整大小框線的視窗框線中。
HTBOTTOM 在視窗的下水準框線中。
HTBOTTOMLEFT 在視窗框線的左下角。
HTBOTTOMRIGHT 在視窗框線的右下角。
AZUREAPTION 在標題列中。
SMTPLIENT 在工作區中。
」的」」是」的 在 [ 關閉] 按鈕中。
HTERROR 在畫面背景或與 HTNOWHERE 相同的視窗 (上,不同之處在于 DefWindowProc 函式會產生系統嗶聲來指出錯誤) 。
HTGROWBOX 在大小方塊中, (與 HTSIZE) 相同。
HTHELP 在 [ 說明] 按鈕中。
HTHSCROLL 在水準捲軸中。
HTLEFT 在視窗的左框線中。
HTMENU 在功能表中。
HTMAXBUTTON [最大化] 按鈕中。
HTMINBUTTON [最小化] 按鈕中。
HTNOWHERE 在畫面背景或視窗之間的分隔線上。
HTREDUCE [最小化] 按鈕中。
HTRIGHT 在視窗的右框線中。
HTSIZE 在大小方塊中, (與 HTGROWBOX) 相同。
HTSYSMENU [系統] 功能表或子視窗中的 [ 關閉 ] 按鈕中。
HTTOP 在視窗的上水準框線中。
HTTOPLEFT 在視窗框線的左上角。
HTTOPRIGHT 在視窗框線的右上角。
HTTRANSPARENT 在目前由相同執行緒中另一個視窗所涵蓋的視窗中。
HTVSCROLL 在垂直捲動條中。
HTZOOM [最大化] 按鈕中。

 

如果游標位在視窗的工作區中, DefWindowProc 就會將 「SAMLIENT 點擊測試」值傳回給視窗程式。 當視窗程式將此程式碼傳回系統時,系統會將游標作用點的螢幕座標轉換為用戶端座標,然後張貼適當的工作區滑鼠訊息。

當游標作用點位於視窗的非工作區時, DefWindowProc 函式會傳回另一個點擊測試值。 當視窗程式傳回下列其中一個點擊測試值時,系統會張貼非工作區滑鼠訊息,並將點擊測試值放在訊息的 wParam 參數和 lParam 參數中的資料指標座標中。

Mouse Sonar

當使用者按下並放開 CTRL 鍵時,滑鼠 Sonar 協助工具功能會簡短地顯示指標周圍的數個同心圓。 此功能可協助使用者在畫面上找出雜亂或解析度設定為高、品質不佳的監視器上的滑鼠指標,或針對視覺受損的使用者。 如需詳細資訊,請參閱 SystemParametersInfo中的下列旗標:

SPI_GETMOUSESONAR

SPI_SETMOUSESONAR

滑鼠消失

滑鼠消失協助工具功能會在使用者輸入時隱藏指標。 當使用者移動滑鼠時,滑鼠指標會重新出現。 此功能會讓指標無法遮蔽輸入的文字,例如電子郵件或其他檔中的文字。 如需詳細資訊,請參閱 SystemParametersInfo中的下列旗標:

SPI_GETMOUSEVANISH

SPI_SETMOUSEVANISH

滑鼠滾輪

滑鼠滾輪結合了滾輪和滑鼠按鍵的功能。 滾輪具有離散、平均間距的標記法。 當您旋轉滾輪時,會傳送滾輪訊息至您的應用程式,因為遇到每個標記法。 滾輪按鈕也可以以一般 Windows 中間 (第三個) 按鈕運作。 按下並放開滑鼠滾輪會傳送標準 WM_MBUTTONUPWM_MBUTTONDOWN 訊息。 按兩下第三個按鈕會傳送標準 WM_MBUTTONDBLCLK 訊息。

滑鼠滾輪可透過 WM_MOUSEWHEEL 訊息支援。

旋轉滑鼠會將 WM_MOUSEWHEEL 訊息傳送至焦點視窗。 DefWindowProc函式會將訊息傳播至視窗的父代。 由於 DefWindowProc 會將訊息傳播至父鏈結,直到找到處理訊息的視窗為止,因此不應該有任何內部轉送訊息。

判斷捲軸數目

應用程式應該使用 SystemParametersInfo 函式來擷取檔捲動的每個捲動作業的行數, (滾輪記號) 。 若要擷取行數,應用程式會進行下列呼叫:

SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)

變數 「pulScrollLines」 指向不帶正負號的整數值,這個值會接收當滑鼠滾輪旋轉而沒有修飾詞鍵時要捲動的建議行數:

  • 如果這個數位是 0,則不應該發生捲動。
  • 如果此數位 是WHEEL_PAGESCROLL,則滾輪滾應該解譯為在捲軸頁面向下或向上頁面區域中按一下一次。
  • 如果要捲動的行數大於可檢視的行數,捲動作業也應該解譯為頁面向下或向上頁作業。

捲軸數目的預設值會是 3。 如果使用者使用主控台中的滑鼠屬性工作表變更滾動線數目,作業系統會將WM_SETTINGCHANGE訊息廣播至所有最上層視窗,並指定SPI_SETWHEELSCROLLLINES。 當應用程式收到 WM_SETTINGCHANGE 訊息時,它接著可以呼叫來取得新的捲軸數目:

SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)

捲動的控制項

下表列出具有捲動功能的控制項, (包括使用者) 所設定的捲動線。

控制 捲動
編輯控制項 垂直和水準。
清單方塊控制項 垂直和水準。
下拉式方塊 當未卸載時,每個捲動都會擷取下一個或上一個專案。 卸載時,每個捲動都會將訊息向前捲動到清單方塊,並據以捲動。
CMD (命令列) 垂直。
樹狀目錄檢視 垂直和水準。
[清單檢視] 垂直和水準。
向上/向下捲動 一次一個專案。
追蹤列捲動 一次一個專案。
Microsoft Rich Edit 1.0 垂直。 請注意,Exchange 用戶端有自己的清單檢視版本,以及沒有滾輪支援的樹狀檢視控制項。
Microsoft Rich Edit 2.0 垂直。

 

使用滾輪偵測滑鼠

若要判斷具有滾輪的滑鼠是否已連接,請使用SM_MOUSEWHEELPRESENT呼叫GetSystemMetricsTRUE的傳回值表示滑鼠已連接。

下列範例來自多行編輯控制項的視窗程式:

BOOL ScrollLines(
     PWNDDATA pwndData,   //scrolls the window indicated
     int cLinesToScroll); //number of times

short gcWheelDelta; //wheel delta from roll
PWNDDATA pWndData; //pointer to structure containing info about the window
UINT gucWheelScrollLines=0;//number of lines to scroll on a wheel rotation

gucWheelScrollLines = SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 
                             0, 
                             pulScrollLines, 
                             0);

case WM_MOUSEWHEEL:
    /*
     * Do not handle zoom and datazoom.
     */
    if (wParam & (MK_SHIFT | MK_CONTROL)) {
        goto PassToDefaultWindowProc;
    }

    gcWheelDelta -= (short) HIWORD(wParam);
    if (abs(gcWheelDelta) >= WHEEL_DELTA && gucWheelScrollLines > 0) 
    {
        int cLineScroll;

        /*
         * Limit a roll of one (1) WHEEL_DELTA to
         * scroll one (1) page.
         */
        cLineScroll = (int) min(
                (UINT) pWndData->ichLinesOnScreen - 1,
                gucWheelScrollLines);

        if (cLineScroll == 0) {
            cLineScroll++;
        }

        cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
        assert(cLineScroll != 0);

        gcWheelDelta = gcWheelDelta % WHEEL_DELTA;
        return ScrollLines(pWndData, cLineScroll);
    }

    break;

視窗啟動

當使用者按一下非使用中最上層視窗或非作用中最上層視窗的子視窗時,系統會將 WM_MOUSEACTI加值稅E 訊息 () 傳送至最上層或子視窗。 系統會在張貼 WM_NCHITTEST 訊息至視窗之後,但在張貼按鈕關閉訊息之前傳送此訊息。 當 WM_MOUSEACTI加值稅E 傳遞至 DefWindowProc 函式時,系統會啟動最上層視窗,然後將按鈕向下訊息張貼至最上層或子視窗。

藉由處理 WM_MOUSEACTI加值稅E,視窗可以控制最上層視窗是否因為按一下滑鼠而變成使用中視窗,以及按一下的視窗是否會收到後續的按鈕向下訊息。 在處理 WM_MOUSEACTI加值稅E之後傳回下列其中一個值,即可這麼做。

意義
MA_ACTI加值稅E 啟動視窗,且不會捨棄滑鼠訊息。
MA_NOACTI加值稅E 不會啟動視窗,也不會捨棄滑鼠訊息。
MA_ACTI加值稅EANDEAT 啟動視窗並捨棄滑鼠訊息。
MA_NOACTI加值稅EANDEAT 不會啟動視窗,但會捨棄滑鼠訊息。

另請參閱

利用滑鼠移動High-Definition