【转】windows程序设计(14):鼠标消息详解
關于鼠標的一些細節知識:
通常,我們發消息時,都是對一個特定的窗口,但是對于鼠標消息卻不然:只要鼠標跨越窗口或者在某窗口中按下鼠標按鍵,那么窗口消息處理程序就會收到鼠標消息,而不管該窗口是否活動或者是否擁有輸入焦點。鼠標消息一個有21種:10個顯示區域消息,11個非顯示區域消息
顯示區域鼠標消息
當鼠標移過窗口的顯示區域時,窗口消息處理程序收到WM_MOUSEMOVE消息。
當在窗口的顯示區域中按下或者釋放一個鼠標按鍵時,窗口消息處理程序會接收到下面這些消息:
?
| 鍵 | 按下 | 釋放 | 按下(雙鍵) |
| 左 | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK |
| 中 | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK |
| 右 | WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK |
只有對三鍵鼠標,窗口消息處理程序才會收到MBUTTON消息。
對于這些消息,其lParam值均含有鼠標的位置:低字字節為x坐標,高字節為y坐標,這兩個坐標是相對于窗口顯示區域左上角的位置。您可以用LOWORD和HIWORD宏來提取這些值:
x = LOWORD (lParam) ; y = HIWORD (lParam) ;wParam的值指示鼠標按鍵以及Shift和Ctrl鍵的狀態:
?
| MK_LBUTTON | 按下左鍵 |
| MK_MBUTTON | 按下中鍵 |
| MK_RBUTTON | 按下右鍵 |
| MK_SHIFT | 按下Shift鍵 |
| MK_CONTROL | 按下Ctrl鍵 |
舉個例子,如果收到了WM_LBUTTONDOWN且wparam & MK_SHIFT為真,則說明左鍵按下時也按下了Shift鍵。
這里要強調一下:
1.WM_MOUSEMOVE消息:當您把鼠標移過窗口的顯示區域時,Windows并不為鼠標的每個可能的圖素位置都產生一個WM_MOUSEMOVE消息。您的程序接收到WM_MOUSEMOVE消息的次數,依賴于鼠標硬件,以及您的窗口消息處理程序在處理鼠標移動消息時的速度。換句話說,Windows不能用未處理的WM_MOUSEMOVE消息來填入消息隊列。
2.對于WM_LBUTTONDOWN和WM_LBUTTONUP消息可能只收到一個!比如在一個窗口中按下鼠標按鍵,然后移動到使用者窗口釋放它,就會出現這種情況。類似的情況,當鼠標按鍵在另一個窗口中被釋放時,窗口消息處理程序只能接收到WM_LBUTTONDOWN消息,而沒有相應的WM_LBUTTONUP消息。
3.關于雙擊鼠標:雙擊的間隔在控制面板里可以設置。但是是否需要相應“雙擊”則是我們自己寫的:在注冊窗口時,必須在窗口風格中包含CS_DBLCLKS標識符。這樣當你雙擊時,系統會收到:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
否則,只會收到:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP
看一個例子程序:
?
程序比較簡單,就不多說了。
那什么是非顯示區域的鼠標消息呢?如果鼠標在窗口的顯示區域之外但還在窗口內,Windows就給窗口消息處理程序發送一條“非顯示區域”鼠標消息。窗口非顯示區域包括標題列、菜單和窗口滾動條。
這些消息通常我們是不用管的,將這些消息傳給DefWindowProc,從而使Windows執行系統功能。
非顯示區域鼠標消息幾乎完全與顯示區域鼠標消息相對應。消息中含有字母“NC”以表示是非顯示區域消息。如果鼠標在窗口的非顯示區域中移動,那么窗口消息處理程序會接收到WM_NCMOUSEMOVE消息。鼠標按鍵產生如表所示的消息:
?
| 鍵 | 按下 | 釋放 | 按下(雙擊) |
| 左 | WM_NCLBUTTONDOWN | WM_NCLBUTTONUP | WM_NCLBUTTONDBLCLK |
| 中 | WM_NCMBUTTONDOWN | WM_NCMBUTTONUP | WM_NCMBUTTONDBLCLK |
| 右 | WM_NCRBUTTONDOWN | WM_NCRBUTTONUP | WM_NCRBUTTONDBLCLK |
但是這些消息參數的意義卻不同:
wParam參數指明移動或者按鼠標按鍵的非顯示區域。
lParam參數的低位word為x坐標,高位word為y坐標,但是,它們是屏幕坐標。
最后一個消息是WM_NCHITTEST,它代表“非顯示區域命中測試”,Windows應用程序通常把這個消息傳送給DefWindowProc,系統會自動的判斷你拖動的是標題欄還是邊框而做出相應。
?
MFC一個解決自己發送WM_NCLBUTTONDOWN消息后收不到WM_ONLBUTTONUP的方法
?
MFC解決自己發送WM_NCLBUTTONDOWN消息收不到WM_LBUTTONUP的方法
??? 最近在做一個MFC拖動窗口的程序,在網上搜到了一個方法,在OnLButtonDown里自己發送
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y));
消息。這樣一來確實能夠在客戶區移動窗口了,但是有一個問題:WM_LBUTTONUP消息被忽略了,寫在OnLButtonUp里的內容根本沒執行。在網上搜解決方法,要么是太復雜,要么沒有很好的解決。最后自己試出了一個方法,經測試可行:
在OnNcLButtonDown函數里完成父類函數后自己發送一個WM_ONLBUTTONUP消息。
如下(CWnd應該換成你自己繼承的父類,因為我直接從CWnd類繼承過來 的,所以是CWnd):
1.處理左鍵按下消息函數:
?
afx_msg void OnLButtonDown(UINT nFlags, CPoint point) {RedrawWindow();Invalidate();//支持拖動PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y));CWnd::OnLButtonDown(nFlags, point); }這樣就發送了非客戶區左鍵按下的消息WM_NCLBUTTONDOWN。
2.處理非客戶區左鍵按下消息函數:
afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point) {CWnd::OnNcLButtonDown(nHitTest,point);PostMessage(WM_LBUTTONUP, NULL, NULL); }PostMessage(WM_LBUTTONUP, NULL, NULL)這一句就是自己發送左鍵放開的消息WM_LBUTTONUP。
根據這個結果,本人猜測CWnd::OnNcLButtonDown可能是要一直執行到鼠標放開時才結束,WM_LBUTTONUP被忽略了。這導致我們收不到WM_LBUTTONUP消息,所以在其后自己發送WM_LBUTTONUP后就能收到WM_LBUTTONUP消息了。
注意:
這個方法鼠標左鍵按下事件是有一秒左右延遲的,當把窗口移動到其他窗口上或控件上,松開再單擊時可能會單擊到那些窗口或控件,大家若有好的方法解決可以發下言。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【转】windows程序设计(14):鼠标消息详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: M2性能可达酷睿i5 26倍 苹果表态:
- 下一篇: 轻薄本用上苹果顶级芯!12英寸MacBo