用WM_NCHITTEST訊息欺騙Windows(一)

來源:互聯網
上載者:User

通常,我們拖動對話方塊視窗的標題列來移動視窗,但有時候,我們想通過滑鼠在客戶區上拖動來移動視窗。

一個容易想到的方案是,處理滑鼠訊息WM_LBUTTONDOWN和WM_LBUTTONUP。在OnLButtonUp函數中計算滑鼠位置的變化,調用MoveWindow實現視窗的移動。

注意,拖動標題列移動視窗的時候,會出現一個矩形框,它提示了視窗移動的當前位置。當滑鼠左鍵放開的時候,視窗就移動到矩形框所在位置。而我們的實現方案中沒有這個功能。

要實現此功能,我們必須自己來畫這些矩形。

事實上,我們沒有必要自己來做這件事情,因為Windows已經給我們做好了。

試想,如果我能夠欺騙Windows,告訴它現在滑鼠正在拖動的是標題列而不是客戶區,那麼視窗移動操作就由Windows來代勞了。

要欺騙Windows並不像想像中的困難,甚至非常簡單。

我們利用一個訊息:WM_NCHITTEST。

MSDN對它的解釋是:

The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.

這個訊息是當滑鼠移動或者有滑鼠鍵按下時候發出的。

Windows用這個訊息來做什嗎? “HITTEST”就是“點擊測試”的意思,WM_NCHITTEST訊息用來擷取滑鼠當前命中的位置。

WM_NCHITTEST的訊息響應函數會根據滑鼠當前的座標來判斷滑鼠命中了視窗的哪個部位,訊息響應函數的傳回值指出了部位,例如它可能會返回HTCAPTION,或者HTCLIENT等。(其傳回值有很多,請查閱MSDN)。

為了便於理解,我先描述一下Windows對滑鼠鍵按下的響應流程:

1.  確定滑鼠鍵點擊的是哪個視窗。Windows會用表記錄當前螢幕上各個視窗的地區座標,當滑鼠驅動程式通知Windows滑鼠鍵按下了,Windows根據滑鼠的座標確定它點擊的是哪個視窗。

2.  確定滑鼠鍵點擊的是視窗的哪個部位。Windows會向滑鼠鍵點擊的視窗發送WM_NCHITTEST訊息,來詢問滑鼠鍵點擊的是視窗的哪個部位。(WM_NCHITTEST的訊息響應函數的傳回值會通知Windows)。通常來說,WM_NCHITTEST訊息是系統來處理的,使用者一般不會主動去處理它(也就是說,WM_NCHITTEST的訊息響應函數通常採用的是Windows預設的處理函數)。

3.  根據滑鼠鍵點擊的部位給視窗發送相應的訊息。例如:如果WM_NCHITTEST的訊息響應函數的傳回值是HTCLIENT,表示滑鼠點擊的是客戶區,則Windows會向視窗發送WM_LBUTTONDOWN訊息;如果WM_NCHITTEST的訊息響應函數的傳回值不是HTCLIENT(可能是HTCAPTION、HTCLOSE、HTMAXBUTTON等),即滑鼠點擊的是非客戶區,Windows就會向視窗發送WM_NCLBUTTONDOWN訊息。

我們有必要詳細討論一下:如果WM_NCHITTEST的訊息響應函數的傳回值是HTCAPTION,即指示了滑鼠點擊了標題列,接下去Windows的處理是怎樣的?

上面已經提到,接下來,Windows會向視窗發送WM_NCLBUTTONDOWN訊息。

MSDN對WM_NCLBUTTONDOWN訊息描述如下:

WM_NCLBUTTONDOWN 

nHittest = (INT) wParam;    // hit-test value 

pts = MAKEPOINTS(lParam);   // position of cursor

WM_NCLBUTTONDOWN的wParam指示了滑鼠點擊的視窗部位,lParam指示了當前滑鼠的座標。

如果應用程式沒有對該訊息響應,則由系統預設處理。

系統預設處理又是怎樣的呢?系統發現wParam指示了滑鼠點擊的是標題列,就會標識當前視窗處於“拖拽狀態”(Windows內部記錄了每個視窗的狀態資訊)。由於標識了“拖拽狀態”,則從此刻起到滑鼠鍵放開之前,你的滑鼠移動狀況完全由Windows跟蹤。它根據滑鼠的移動,使得視窗作“同步”移動。

注意,這個過程中,視窗不會收到WM_NCMOUSEMOVE訊息,因為視窗和滑鼠是“同步”移動的,你的滑鼠相對於視窗是靜止的。(這些細節你可以自己寫個樣本來測試並分析得出,事實上我也是這麼做的。如果我的觀點有錯誤,歡迎指正)。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.