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處理無邊框視窗縮放問題:
響應訊息,訊息響應函數如下:
LRESULT OnNcHitTest(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
//這裡是防止在最大化的時候能縮放視窗(在沒有WS_THICKFRAME風格的情況下需要這樣處理下)
if (::IsZoomed(m_hWnd))
{
return TRUE;
}
POINT MousePos;
MousePos.x = GET_X_LPARAM(lParam);
MousePos.y = GET_Y_LPARAM(lParam);
::ScreenToClient(m_hWnd,&MousePos);
RECT rc;
int retn = TRUE;
::GetClientRect(m_hWnd,&rc);
int iWidth = rc.right - rc.left;
int iHeight = rc.bottom - rc.top;
if ( PtInRect(CRect(5, 0, iWidth - 100, 5), MousePos ))
retn = HTTOP;
else if (PtInRect( CRect(0, 5, 5, iHeight-5), MousePos ))
retn = HTLEFT;
else if (PtInRect( CRect(iWidth - 5, 25, iWidth, iHeight - 5), MousePos ))
retn = HTRIGHT;
else if (PtInRect( CRect(5, iHeight - 5, iWidth - 5, iHeight), MousePos ))
retn = HTBOTTOM;
else if (PtInRect( CRect( 0, 0, 5, 5 ), MousePos ))
retn = HTTOPLEFT;
else if (PtInRect( CRect( 0, iHeight - 5, 5, iHeight), MousePos ))
retn = HTBOTTOMLEFT;
else if (PtInRect( CRect( iWidth - 5, iHeight - 5, iWidth, iHeight), MousePos ))
retn = HTBOTTOMRIGHT;
return retn;
}