很多時候,爲了界面的美觀,我們會隱藏標題欄,而在客戶區通過自繪模擬標題欄。但是這樣處理,會導致窗體無法移動。下面提供幾種移動方法:
1、採用欺騙的方式。即當鼠標點擊客戶區的時候,我們欺騙windows,讓windows認爲我們點擊在了標題欄,這樣,拖動過程就通過windows進行處理了。因此可以大大減少我們的代碼量。具體方法如下:
響應鼠標左鍵按下消息WM_LBUTTONDOWN,相應函數中,直接發送欺騙消息:
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
WM_NCLBUTTONDOWN即左鍵在非客戶區按下,HTCAPTION即標題欄,所以採用這種方式,就可以實現無標題欄對話框的移動問題了。
那麼問題來了。。。
採用這種操作後,會導致我們的對話框無法響應WM_LBUTTONUP消息,同時在我編寫程序過程中發現WM_NCLBUTTONUP也一般不能響應。當然,可以通過註冊WM_MOUSEHOVER以及WM_MOUSELEAVE消息,響應這兩個消息去處理相應的代碼,或者採用下鉤子的方法,在鉤子中正確發送消息,不過不推薦這種方法,實現也比較麻煩。
所以下面提供第二種方法。
2、在WM_MOUSEMOVE消息中,自己處理窗口移動。具體就是先判斷鼠標左鍵是否處於按下,如果是的話,就獲取鼠標移動到的位置,然後將窗口進行移動就可以了。具體實現如下:
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point) { static CPoint PrePoint = CPoint(0, 0); if(MK_LBUTTON == nFlags) { if(point != PrePoint) { CPoint ptTemp = point - PrePoint; CRect rcWindow; GetWindowRect(&rcWindow); rcWindow.OffsetRect(ptTemp.x, ptTemp.y); MoveWindow(&rcWindow); return ; } } PrePoint = point; CDialog::OnMouseMove(nFlags, point); }
通過上面的消息,就能夠進行窗口移動了。然而,如果僅僅響應上面的消息發現兩個問題:第一,當鼠標按住左鍵快速移動的時候,鼠標會移出窗口,窗口不動了,拖動效果不好;第二,左鍵釋放消息在上面這種情況下沒有響應。解決方法如下:
首先左鍵按下消息中設置鼠標捕獲
SetCapture();
在左鍵釋放消息中釋放鼠標捕獲
RealeseCapture();
通過上面的處理,就可以完美拖動,同時,左鍵擡起的消息也不會受影響。
因此,第一種方法較爲簡潔,適合不需要響應鼠標其它消息的情況;第二種方法相對麻煩一些,不過實現效果也很好,並且不影響其他消息。