WS_POPUP 最大化如何不遮挡任务栏

在桌面开发时,我们有时会创建样式为 WS_POPUP 的窗口,然后自绘标题栏。当窗口最大化时,会覆盖整个屏幕,盖住了任务栏,这通常不是我们想要的效果。

在桌面开发时,我们有时会创建样式为 WS_POPUP 的窗口,然后自绘标题栏。当窗口最大化时,会覆盖整个屏幕,盖住了任务栏,这通常不是我们想要的效果。

image

为了避免遮挡任务栏,一般的做法是响应 WM_GETMINMAXINFO 消息,限制其最大化后的位置,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void CwspopupmaximizeDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL);
    if (monitor)
    {
        // 获取窗口所在屏幕
        MONITORINFO info = { 0 };
        info.cbSize = sizeof(MONITORINFO);
        if (GetMonitorInfo(monitor, &info))
        {
            // 限制为工作区范围
            CRect rcWork = info.rcWork;
            lpMMI->ptMaxPosition = { 0, 0 };
            lpMMI->ptMaxSize.x = rcWork.Width();
            lpMMI->ptMaxSize.y = rcWork.Height();
        }
    }

    CDialogEx::OnGetMinMaxInfo(lpMMI);
}

写个测试程序、编译、运行,效果完美

image

然而当多屏幕时,把测试程序放到副屏幕上,最大化后窗口不但遮住了任务栏,而且横向也超出屏幕,被截掉一部分。

image

查阅 MSDN 中关于 **MINMAXINFO**** 结构的描述**

如果窗口位于第二屏,MINMAXINFO 中的坐标会进行一些 转换 然后再应用到第二屏上。但究竟是什么转换呢,MSDN 上没有明确指出。

经过搜寻,在微软 The Old New Thing 中找到了进一步的描述:

如此一来就能解释之前的问题了,我的主屏是 1920x1080, 第二屏是 2560x1440,当在第二屏上最大化时,得到的第二屏桌面大小为 2560x1410,超出了主屏大小,所以得按照差值方式调整。

要解决此问题,我们可以在 WM_SIZE 中判断 nType == SIZE_MAXIMIZED 时,修正窗口大小:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void CwspopupmaximizeDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);

    if (nType == SIZE_MAXIMIZED)
    {
        SetDlgItemText(ID_MAXMIZE_RESTORE, L"restore");

        HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL);
        if (monitor)
        {
            MONITORINFO info = { 0 };
            info.cbSize = sizeof(MONITORINFO);
            if (GetMonitorInfo(monitor, &info))
            {
                CRect rcWork = info.rcWork;
                SetWindowPos(NULL, rcWork.left, rcWork.top, rcWork.Width(), rcWork.Height(), SWP_SHOWWINDOW);
            }
        }
    }
    else if (nType == SIZE_RESTORED)
    {
        SetDlgItemText(ID_MAXMIZE_RESTORE, L"maximize");
    }
    Invalidate();
} 

参考资料:

How does the window manager adjust ptMaxSize and ptMaxPosition for multiple monitors?

Licensed under CC BY-NC-SA 4.0
Last updated on 2025-11-11 00:00