在Windows平臺上,鼠標(biāo)左鍵的按下、松開、快速的兩次點(diǎn)擊會產(chǎn)生WM_LBUTTONDOWN、WM_LBUTTONUP和 WM_LBUTTONDBLCLK消息,但是Windows根據(jù)什么來區(qū)分連續(xù)的兩次鼠標(biāo)按鍵操作,是兩次獨(dú)立的單擊,還是一次雙擊呢?最近在解決一個問題時,通過使用Spy++和查閱MSDN,弄清楚了這個問題。簡單總結(jié)如下:
Windows根據(jù)兩個條件來做這個區(qū)分:
(1)雙擊的時間間隔
這是很容易想到的。更準(zhǔn)確的說法是這樣的,兩次單擊會產(chǎn)生四個鼠標(biāo)點(diǎn)擊消息,如果第三個消息(第二次按下)和第二個消息(第一次彈起引發(fā)的 WM_LBUTTONUP)間隔短于指定值,則把第三個消息處理成WM_LBUTTONDBLCLK消息;第四個消息照舊,WM_LBUTTONUP。
這個指定的時間間隔,在Windows XP SP2上缺省是0.5秒,其他操作系統(tǒng)可能相同。通過::GetDoubleClickTime調(diào)用可以得到這個值。
這個值是可以設(shè)置的。有兩種方法設(shè)置這個值: ::SetDoubleClickTime調(diào)用,或者以SPI_SETDOUBLECLICKTIME為第一個參數(shù)調(diào)用::SystemParametersInfo。設(shè)置的結(jié)果對系統(tǒng)中其他的應(yīng)用程序也起作用。
(2)兩次鼠標(biāo)擊點(diǎn)的空間距離
在第一次點(diǎn)擊時,Windows以擊點(diǎn)為中心,檢測一個矩形區(qū)域,如果第二次點(diǎn)擊不落在這個區(qū)域內(nèi),那就不把第三個消息算作WM_LBUTTONDBLCLK消息。
這個矩形區(qū)域的缺省大小,在Windows XP SP2上缺省是4pt×4pt??梢砸許M_CXDOUBLECLK或SM_CYDOUBLECLK為參數(shù)調(diào)用::GetSystemMetrics得到。
這個值也是可以設(shè)置的。設(shè)置的方法是通過SPI_SETDOUBLECLKWIDTH或SPI_SETDOUBLECLKHEIGHT為第一個參數(shù)來調(diào)用::SystemParametersInfo。設(shè)置的結(jié)果對系統(tǒng)中其他的應(yīng)用程序也起作用。
因此,連續(xù)兩次按下和彈起鼠標(biāo)左鍵:
如果不符合以上兩個條件,產(chǎn)生的消息是:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP
如果符合以上兩個條件,產(chǎn)生的消息則是:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
以上結(jié)論還隱含兩個要點(diǎn):
(1)不管是算作兩次連續(xù)的單擊,還是一次雙擊,第一、二和四個消息都是不受影響的。在接受到一個雙擊消息之前,應(yīng)用程序總是會先收到一個 WM_LBUTTONDOWN和一個WM_LBUTTONUP消息,之后是WM_LBUTTONUP消息。應(yīng)用程序應(yīng)該對各種消息做出恰當(dāng)?shù)奶幚恚?br>(2)第二個消息和第三個消息是關(guān)鍵,必須被連續(xù)發(fā)到同一個窗口過程才能被處理。開發(fā)中常見的一個錯誤是這樣的:在處理第一個消息WM_LBUTTONDOWN 或者WM_LBUTTONUP時,通過SetCapture捕獲后續(xù)的鼠標(biāo)消息,轉(zhuǎn)發(fā)到別的窗口,導(dǎo)致原窗口不能識別雙擊,而這個雙擊可能正是期望的。