一些新定義:
熱點:鼠標其實就是一個位圖,但是從應用的角度看,他在用戶區域裏,其實指向唯一的一個像素,這個像素就是熱點(hot spot)。
參數: 當鼠標移過窗口的顯示區域時,窗口消息處理程序收到WM_MOUSEMOVE消息。當在窗口的顯示區域中按下或者釋放一個鼠標按鍵時,窗口消息處理程序會接收到下面這些消息:
鍵 |
按下 |
釋放 |
按下(雙鍵) |
左 |
WM_LBUTTONDOWN |
WM_LBUTTONUP |
WM_LBUTTONDBLCLK |
中 |
WM_MBUTTONDOWN |
WM_MBUTTONUP |
WM_MBUTTONDBLCLK |
右 |
WM_RBUTTONDOWN |
WM_RBUTTONUP |
WM_RBUTTONDBLCLK |
對於所有這些消息來說,其lParam值均含有鼠標的位置:低字組爲x座標,高字組爲y座標,這兩個座標是相對於窗口顯示區域左上角的位置。您可以用LOWORD和HIWORD宏來提取這些值:
wParam的值指示鼠標按鍵以及Shift和Ctrl鍵的狀態。您可以使用表頭文件WINUSER.H中定義的位屏蔽來測試wParam。MK前綴代表「鼠標按鍵」。
MK_LBUTTON | 按下左鍵 |
MK_MBUTTON | 按下中鍵 |
MK_RBUTTON | 按下右鍵 |
MK_SHIFT | 按下Shift鍵 |
MK_CONTROL | 按下Ctrl鍵 |
例如,如果收到了WM_LBUTTONDOWN消息,而且值
wparam & MK_SHIFT
是TRUE(非0),您就知道當左鍵按下時也按下了Shift鍵。
刷新問題:當你的鼠標在用戶區域中划動的時候,windows不會爲每個像素生成一個WM_MOUSEMOVE消息,受到
WM_MOUSEMOVE消息的頻率的大小是要看你鼠標的硬件指數以及你的消息處理函數處理消息的速度.
窗口的激活問題:當鼠標在不活動窗口中按下左鍵時,windows會先將這個窗口激活,然後再往他的消息處理函數隊列中加入一個WM_LBUTTONDOWN消息.
所以,當一個窗口被接受到WM_LBUTTOMDOWN時就可以說明,這個窗口是活動窗口.然後一個窗口處理函數會接受到一個沒有對應的WM_LBOTTONDOWN的WM_LBUTTONUP消息.
這種情況發生在,你按左鍵時在一個窗口,然後鼠標拖動到另一個窗口,然後釋放左鍵.所以按鍵消息會有兩個例外:
1.消息處理程序可以「攔截鼠標」並且連續地接收鼠標消息,即使此時鼠標在該窗口顯示區域之外。您將在本章的後面學習如何攔截鼠標。
2.顯示一個系統模態消息框或者系統模態對話框,那麼其它程序就不能接收鼠標消息。當系統模態消息框或者對話框活動時,禁止切換到其它窗口或者程序。一個顯示系統模態消息框的例子,是當您關閉Windows時。
雙擊事件:你的程序要響應雙擊時間必須包括CS_DBLCLKS標示符....
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
如果你的程序中不包括CS_DBLCLKS那麼,你點擊鼠標兩次在很快的時間間隔內,你的消息處理函數會收到這樣的消息:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP //在這種情況下你可以通過GetMessageTime(void)來得到得到消息的相對時間,從而實現雙擊事件
如果你的程序包括CS_DBLCLKS,當雙擊鼠標時就會收到:
WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK //windows將第2個WM_LBUTTONDOWN替換爲WM_LBUTTONCLK WM_LBUTTONUP
非顯示區域鼠標事件:非顯示區域鼠標事件有以下幾種:
Button | Pressed | Released | Pressed (Second Click) |
Left | WM_NCLBUTTONDOWN | WM_NCLBUTTONUP | WM_NCLBUTTONDBLCLK |
Middle | WM_NCMBUTTONDOWN | WM_NCMBUTTONUP | WM_NCMBUTTONDBLCLK |
Right | WM_NCRBUTTONDOWN | WM_NCRBUTTONUP | WM_NCRBUTTONDBLCLK |
注意一下,其實就是在顯示區域的事件名稱之前加了NC(NonClient).
非顯示區域的鼠標事件的參數值和顯示區域的有些不同.
wParam:指明移動或者按鼠標按鍵的非顯示區域,一般是以HT開頭的標示符.
lParam:鼠標的x,y座標,同樣低八位爲x座標,高八位爲y座標,但是這個是屏幕座標,要將屏幕座標轉化爲顯示區域座標可以調用:
ScreenToClient (hwnd, &pt); ClientToScreen (hwnd, &pt);
Hit-Test消息:消息名字爲WM_NCHITTEST.這個消息是優先於所有其他的鼠標對於非顯示區域鼠標消息,在處理WM_NCHITTEST時,
從DefWindowProc傳回的值將成爲鼠標消息中的wParam參數,這個值可以是任意非顯示區域鼠標消息的wParam值再加上以下內容:
HTCLIENT HTNOWHERE HTTRANSPARENT HTERROR | 顯示區域 不在窗口中 窗口由另一個窗口覆蓋 使DefWindowProc產生警示用的嗶聲 |
如果你想在你的程序中攔截鼠標消息,就可以這樣做:
case WM_NCHITTEST:
return (LRESULT)HTNOWHERE;
捕獲鼠標:在有的應用程序中,需要對不在自己程序的顯示區域之內的鼠標事件也做處理,那麼就要用到捕獲鼠標的技術,捕獲鼠標可以用WIN32 API函數來實現:
SetCapture(
HWND hwnd //捕獲鼠標的窗口句柄
);
返回值:如果函數成功的話,就返回前一個捕獲鼠標的窗口句柄,如果沒有那麼一個窗口就返回NULL
鼠標滾動:從WINNT開始,MS支持鼠標的滾動,應用程序需要處理鼠標滾動消息時,就要截獲wm-mouseweel消息
WM_MOUSEWHEEL
fwKeys = LOWORD(wParam); // key flags
zDelta = (short) HIWORD(wParam); // wheel rotation,正數就是向前滾動,這個數是WHEEL_DELTA(120)的倍數或約數
xPos = (short) LOWORD(lParam); // horizontal position of pointer(屏幕座標)
yPos = (short) HIWORD(lParam); // vertical position of pointer(屏幕座標)