LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_LBUTTONDOWN: { OnMouseLButtonDown(wParam, lParam); break; } case WM_LBUTTONUP: { OnMouseLButtonUp(wParam, lParam); break; } case WM_MOUSEMOVE: { OnMouseLDownMove(wParam, lParam); break; } case WM_NCMOUSEMOVE: { OnMouseNcLDownMove(wParam, lParam); break; } case WM_NCLBUTTONUP: { OnMouseNcLButtonUp(wParam, lParam); break; } case WM_NCLBUTTONDOWN: { OnMouseNcLButtonDown(wParam, lParam); break; } } return __super::HandleMessage(uMsg, wParam, lParam); } void OnMouseNcLButtonDown(WPARAM wParam, LPARAM lParam) { POINT point; point.x = (short)LOWORD( lParam); point.y = (short)HIWORD( lParam); ClientToScreen(m_hWnd, &point); m_ptPrev = point; } void OnMouseNcLButtonUp(WPARAM wParam, LPARAM lParam) { POINT ptIn; ptIn.x = (short)LOWORD( lParam); ptIn.y = (short)HIWORD( lParam); POINT pt = ptIn; ClientToScreen(m_hWnd, &pt); RECT rectWnd, rcWorkArea; SIZE sz; GetWindowRect(m_hWnd, &rectWnd); OffsetRect(&rectWnd, m_ptPrev.x - m_ptMouseDown.x, m_ptPrev.y - m_ptMouseDown.y); OffsetRect(&rectWnd, pt.x - m_ptPrev.x, pt.y - m_ptPrev.y); ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE); sz.cx = rectWnd.right - rectWnd.left; sz.cy = rectWnd.bottom - rectWnd.top; if (rectWnd.left + sz.cx > rcWorkArea.right) { rectWnd.left = rcWorkArea.right - sz.cx; } else if(rectWnd.left < 0) { rectWnd.left = 0; } if(rectWnd.top < 0) { rectWnd.top = 0; } else if(rectWnd.top + sz.cy > rcWorkArea.bottom ) { rectWnd.top = rcWorkArea.bottom - sz.cy; } m_ptPrev.x = m_ptPrev.y = m_ptMouseDown.x = m_ptMouseDown.y = -1; GetWindowRect(m_hWnd, &rectWnd); } void OnMouseLButtonDown(WPARAM wParam, LPARAM lParam) { m_bMouseState = LNCDOWN; // 按下标题栏时拖放 ::SendMessage(m_hWnd, WM_NCLBUTTONDOWN, wParam, lParam); } void OnMouseLButtonUp(WPARAM wParam, LPARAM lParam) { POINT ptIn, pt; pt.x = ptIn.x = (short)LOWORD(lParam); pt.y = ptIn.y = (short)HIWORD(lParam); HRGN hRgn = CreateRectRgn(0, 0, 0, 0); GetWindowRgn(m_hWnd, hRgn); ClientToScreen(m_hWnd, &pt); if (!PtInRegion(hRgn, ptIn.x, ptIn.y) && (m_bMouseState == NOEVENT)) //释放鼠标捕捉 { ::SendMessage(m_hWnd, WM_MOUSELEAVE, 0, 0); } DeleteObject(hRgn); if ((m_bMouseState == LNCDOWN) || (m_bMouseState == NOEVENT)) { ::SendMessage(m_hWnd, WM_NCMOUSEMOVE, wParam, lParam); } } void OnMouseLDownMove(WPARAM wParam, LPARAM lParam) { POINT ptIn, pt; pt.x = ptIn.x = (short)LOWORD(lParam); pt.y = ptIn.y = (short)HIWORD(lParam); HRGN hRgn = CreateRectRgn(0, 0, 0, 0); GetWindowRgn(m_hWnd, hRgn); ClientToScreen(m_hWnd, &pt); if (!PtInRegion(hRgn, ptIn.x, ptIn.y) && (m_bMouseState == NOEVENT)) //释放鼠标捕捉 { ::SendMessage(m_hWnd, WM_MOUSELEAVE, 0, 0); } DeleteObject(hRgn); if ((m_bMouseState == LNCDOWN) || (m_bMouseState == NOEVENT)) { ::SendMessage(m_hWnd, WM_NCMOUSEMOVE, wParam, lParam); } } void OnMouseNcLDownMove(WPARAM wParam, LPARAM lParam) { UINT nFlags = (UINT)wParam; POINT point; point.x = (short)LOWORD( lParam); point.y = (short)HIWORD( lParam); if (nFlags & MK_LBUTTON) { RECT rectWnd; POINT pt = point; GetWindowRect(m_hWnd, &rectWnd); ClientToScreen(m_hWnd, &pt); OffsetRect(&rectWnd, pt.x - m_ptPrev.x , pt.y - m_ptPrev.y); m_ptPrev = pt; int nWidth = rectWnd.right - rectWnd.left; int nHeight = rectWnd.bottom - rectWnd.top; RECT rcWorkArea; ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE); if(rectWnd.left < rcWorkArea.left) { rectWnd.left = rcWorkArea.left; } else if (rectWnd.left + nWidth > rcWorkArea.right) { rectWnd.left = rcWorkArea.right - nWidth; } if (rectWnd.top < rcWorkArea.top) { rectWnd.top = rcWorkArea.top; } else if (rectWnd.top + nHeight > rcWorkArea.bottom) { rectWnd.top = rcWorkArea.bottom - nHeight; } ::MoveWindow(m_hWnd, rectWnd.left, rectWnd.top, nWidth, nHeight, TRUE); } }
private:enum MOUSESTATE{NOEVENT, LNCDOWN, LCLIENTDOWN, LSIZEDOWN};MOUSESTATE m_bMouseState; //记录鼠标状态POINT m_ptMouseDown; //记录鼠标按下时的位置POINT m_ptPrev; //记录鼠标前一次的位置