MFC 中实现在客户区拖动来拖动窗口的方法总结

VC++实现无标题栏对话框的拖动 其实说白了就是欺骗,欺骗谁了?呵呵,当然是欺骗windows,本来是移动标题栏可以拖动窗体,那么我们现在是拖动客户区来移动,当我们拖动标题栏的时候windows产生一个WM_NCHITTEST消息,这个消息确定鼠标点击的哪个位置,这个消息返回一个值,从而确定是“客户区”还是“非客户区”,当返回的值是HTCAPTION,说明这时拖动的是标题栏

  那么我们现在就来欺骗,当用户拖动非标题栏的时候直接返回一个HTCAPTION状态就可以 ,看代码

  在对话框中重载消息WM_NCHITTEST ,添加如下代码

  CRect rc;

  GetClientRect(&rc);//得到客户区的大小

  ClientToScreen(&rc);//坐标转换

  return rc.PtInRect(pt) ? HTCAPTION : //当用户鼠标的点击位置在客户区的时候直接返回HTCAPTION

  当然了上面的方法只是适合对话框,那我们有的时候拖动的却是视图,那怎么设计呢!首先大家明白这样一个道理,Windows在发送WM_NCHITTEST消息时,是将它发送到鼠标光标下的框架/视图最顶层非透明窗口,由于视图首先获得WM_NCHITTEST 消息。所以只要在视图的WM_NCHITTEST消息处理例程中返回HTTRANSPARENT,直接在视图的WM_NCHITTEST消息中添加如下代码

  return HTTRANSPARENT; //返回这个状态标志

  上面的方法看了网上的资料总结的,当然了还有更简单的,只要在OnLButtonDown事件中添加如下一句代码也可以实现

  PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));

  这里注意,在视图窗口中添加可能不起作用,这段代码只能适合对话框类型

可以通过以下步骤实现: 1. 在 MFC 应用程序创建一个无边框窗体,可以通过在窗口类的 PreCreateWindow 函数设置窗口样式来实现,例如: ```c++ BOOL CMyWnd::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE; cs.style &= ~WS_BORDER; // 去掉边框样式 cs.style |= WS_THICKFRAME; // 添加调整大小的样式 return TRUE; } ``` 2. 在窗体类添加以下成员变量: ```c++ BOOL m_bDrag; // 标记是否正在拖动窗体边缘 CPoint m_ptOrigin; // 记录鼠标按下时的位置 ``` 3. 响应 WM_NCHITTEST 消息,判断鼠标位置是否在窗体边缘,并返回对应的鼠标样式: ```c++ UINT CMyWnd::OnNcHitTest(CPoint point) { UINT nHitTest = CWnd::OnNcHitTest(point); if (nHitTest == HTCLIENT) { CRect rect; GetWindowRect(&rect); // 判断鼠标位置是否在窗体边缘 if (point.x < rect.left + 5) nHitTest = HTLEFT; else if (point.x > rect.right - 5) nHitTest = HTRIGHT; if (point.y < rect.top + 5) nHitTest = HTTOP; else if (point.y > rect.bottom - 5) nHitTest = HTBOTTOM; if (point.x < rect.left + 5 && point.y < rect.top + 5) nHitTest = HTTOPLEFT; else if (point.x < rect.left + 5 && point.y > rect.bottom - 5) nHitTest = HTBOTTOMLEFT; else if (point.x > rect.right - 5 && point.y < rect.top + 5) nHitTest = HTTOPRIGHT; else if (point.x > rect.right - 5 && point.y > rect.bottom - 5) nHitTest = HTBOTTOMRIGHT; } return nHitTest; } ``` 4. 响应 WM_NCLBUTTONDOWN 消息,判断鼠标按下的位置是否在窗体边缘,如果是,则记录鼠标按下时的位置,并标记正在拖动边缘: ```c++ void CMyWnd::OnNcLButtonDown(UINT nHitTest, CPoint point) { if (nHitTest == HTLEFT || nHitTest == HTRIGHT || nHitTest == HTTOP || nHitTest == HTBOTTOM || nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT) { m_bDrag = TRUE; m_ptOrigin = point; SetCapture(); } CWnd::OnNcLButtonDown(nHitTest, point); } ``` 5. 响应 WM_NCMOUSEMOVE 消息,如果正在拖动边缘,则根据鼠标移动的距离调整窗体大小: ```c++ void CMyWnd::OnNcMouseMove(UINT nHitTest, CPoint point) { if (m_bDrag) { CRect rect; GetWindowRect(&rect); int dx = point.x - m_ptOrigin.x; int dy = point.y - m_ptOrigin.y; switch (nHitTest) { case HTLEFT: rect.left += dx; break; case HTRIGHT: rect.right += dx; break; case HTTOP: rect.top += dy; break; case HTBOTTOM: rect.bottom += dy; break; case HTTOPLEFT: rect.left += dx; rect.top += dy; break; case HTTOPRIGHT: rect.right += dx; rect.top += dy; break; case HTBOTTOMLEFT: rect.left += dx; rect.bottom += dy; break; case HTBOTTOMRIGHT: rect.right += dx; rect.bottom += dy; break; } MoveWindow(&rect); } CWnd::OnNcMouseMove(nHitTest, point); } ``` 6. 响应 WM_NCLBUTTONUP 消息,结束拖动边缘: ```c++ void CMyWnd::OnNcLButtonUp(UINT nHitTest, CPoint point) { if (m_bDrag) { m_bDrag = FALSE; ReleaseCapture(); } CWnd::OnNcLButtonUp(nHitTest, point); } ``` 以上就是实现用鼠标拖动窗体边缘实现窗体大小变化的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值