使窗口具备拖动到边界自动最大化/还原的特性

从win7开始,windows的特性中具备了拖动窗口到屏幕边界时最大化,还原,或者占据半个工作区的功能,

如果希望自己的窗口具体这种特性,那么需要在窗口属性中添加 WS_BORDERG与WS_THICKFRAME,

但是对于DirectUI绘制的一些窗口时,在窗口创建时就添加WS_THICKFRAME会造成窗口的边框由系统绘制,不符合设计效果



解决方法是创建时使用

WS_BORDER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX 

而后处理WM_NCCALCSIZE消息



 
 
  1. LRESULT EditorFrame::OnNcCalcSzie(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2. {
  3. bHandled = TRUE;
  4. LONG style = GetWindowLong(m_hWnd, GWL_STYLE);
  5. if ((style & WS_THICKFRAME) == 0)
  6. SetWindowLong(m_hWnd, GWL_STYLE, style | WS_THICKFRAME);
  7. return S_OK;
  8. }

此时应该已经具备了拖动边缘响应最大化/还原的特性,但是可能会有新的问题,就是最大化的边框并不切合显示器的边,


此时需要处理WM_GETMINMAXINFO消息 


 
 
  1. LRESULT EditorFrame::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2. {
  3. bHandled = TRUE;
  4. MINMAXINFO* lpmmi = (MINMAXINFO*)lParam;
  5. lpmmi->ptMaxPosition.x = 0;
  6. lpmmi->ptMaxPosition.y = 0;
  7. MONITORINFO oMonitor = {};
  8. oMonitor.cbSize = sizeof(oMonitor);
  9. ::GetMonitorInfo(::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &oMonitor);
  10. lpmmi->ptMaxSize.x = oMonitor.rcWork.right - oMonitor.rcWork.left;
  11. lpmmi->ptMaxSize.y = oMonitor.rcWork.bottom - oMonitor.rcWork.top;
  12. SIZE mini_size = { 0 };
  13. mini_size.cx = NO_BORDER_MINI_WIDTH;
  14. mini_size.cy = NO_BORDER_MINI_HEIGHT;
  15. lpmmi->ptMinTrackSize.x = mini_size.cx;
  16. lpmmi->ptMinTrackSize.y = mini_size.cy;
  17. return S_OK;
  18. }



这样前一个问题差不多解决了,但是在win10系统下贴合左边框时出来了边框绘制的问题


经过尝试,处理WM_NCACTIVATE消息可以避免这种情况出现的可能性


 
 
  1. LRESULT EditorFrame::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2. {
  3. bHandled = TRUE;
  4. if (::IsIconic(m_hWnd)) bHandled = FALSE;
  5. return (wParam == 0) ? TRUE : FALSE;
  6. }






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现拖动窗口到屏幕边缘自动最大化,可以在窗口的消息处理函数中捕捉 WM_WINDOWPOSCHANGING 消息,然后判断窗口是否位于屏幕边缘,如果是,则将窗口状态设置为最大化。以下是具体的实现步骤: 1. 在窗口类的消息处理函数中添加对 WM_WINDOWPOSCHANGING 消息的处理。 ```cpp LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_WINDOWPOSCHANGING: OnWindowPosChanging((WINDOWPOS*)lParam); break; // 其他消息处理 } } ``` 2. 实现 OnWindowPosChanging 函数,判断窗口位置是否位于屏幕边缘,并设置窗口状态。 ```cpp void OnWindowPosChanging(WINDOWPOS* pWndPos) { if (pWndPos->flags & SWP_NOMOVE) return; // 获取屏幕工作区矩形(不包括任务栏) RECT rcWorkArea; SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); // 判断窗口是否位于屏幕边缘 if (pWndPos->x <= rcWorkArea.left) { pWndPos->x = rcWorkArea.left; pWndPos->cx = rcWorkArea.right - rcWorkArea.left; } else if (pWndPos->x + pWndPos->cx >= rcWorkArea.right) { pWndPos->x = rcWorkArea.right - pWndPos->cx; } if (pWndPos->y <= rcWorkArea.top) { pWndPos->y = rcWorkArea.top; pWndPos->cy = rcWorkArea.bottom - rcWorkArea.top; } else if (pWndPos->y + pWndPos->cy >= rcWorkArea.bottom) { pWndPos->y = rcWorkArea.bottom - pWndPos->cy; } } ``` 在 OnWindowPosChanging 函数中,首先判断了窗口是否被移动,如果没有移动则直接返回。接着使用 SystemParametersInfo 函数获取屏幕的工作区矩形,然后判断窗口是否位于屏幕边缘,如果是,则将窗口状态设置为最大化或调整窗口大小使其占据整个屏幕工作区。 注意:使用 SystemParametersInfo 函数需要包含 windows.h 头文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值