Winapi 更改最大化窗口的样式

Winapi 更改最大化窗口的样式,winapi,Winapi,我想要一个窗口,它的行为与正常的重叠窗口相同,除了它在最大化时没有capton栏(以便为客户端区域腾出更多空间)。 我可以从窗口样式中删除WS_CAPTION | WS_SYSMENU。 但是,我无法找到正确的窗口位置和大小: 通过使用边框宽度扩展工作区矩形,可以最大化普通窗口。这使得边界“悬挂”在外面。当我删除WS\u CAPTION时,边框是不同的(在我的例子中是3对4像素),因此我必须以某种方式重新定位窗口 我所尝试的: 首先更改样式,然后最大化:这不会最大化工作区域,而是全屏显示。看起

我想要一个窗口,它的行为与正常的重叠窗口相同,除了它在最大化时没有capton栏(以便为客户端区域腾出更多空间)。 我可以从窗口样式中删除
WS_CAPTION | WS_SYSMENU
。 但是,我无法找到正确的窗口位置和大小:

通过使用边框宽度扩展工作区矩形,可以最大化普通窗口。这使得边界“悬挂”在外面。当我删除
WS\u CAPTION
时,边框是不同的(在我的例子中是3对4像素),因此我必须以某种方式重新定位窗口

我所尝试的:

  • 首先更改样式,然后最大化:这不会最大化工作区域,而是全屏显示。看起来这是窗口管理器的一项功能,它依赖于
    WS\u CAPTION
    样式。除此之外,边界是“悬挂”正确的

  • 首先最大化,然后更改样式、位置和大小:

    • 我找不到API来获得最大的大小和位置。然而,最近的监视器的工作区域在我看来很好
    • 我找不到用适当的“悬挂边框”来扩展window rect的API
      AdjustWindowRectEx
      几乎就在那里,但是非客户端区域与边框不同(显然它还包括标题和菜单)。我还尝试自己使用
      GetSystemMetrics
      值进行计算,但这似乎太不可预测了。边框可以是
      SM\u CXSIZEFRAME
      ,或者
      SM\u CXSIZEFRAME
      +
      SM\u CXPADDEDBORDER
      ,或者
      SM\u CXFIXEDFRAME
      ,这可能取决于操作系统版本、主题以及其他内容
是否有可能以稳健的“官方”方式实现这一点?

我把我自己的答案放在下面,但它太粗糙了。

您已经删除了标题。如果不想显示边框,请同时删除边框。准备稍后恢复边界。找到桌面矩形,并将窗口定位到该矩形中。全屏窗口可以有
WS_重叠
WS_弹出
标志,不带标题和边框。例如:

void switch_view()
{
    RECT rc;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
    DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
    if(style & WS_CAPTION)
    {
        SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPED);
        SetWindowLongPtr(hwnd, GWL_EXSTYLE, 0);
        SetWindowPos(hwnd, NULL, 0, 0, rc.right, rc.bottom,
            SWP_SHOWWINDOW | SWP_FRAMECHANGED);
    }
    else
    {
        SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
            SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    }
}

这是我多次尝试后得到的

  • 边界问题解决了。正如其他人所建议的,我删除了带有标题的边框。因此无需计算。也不需要为带有边框的标题窗口计算边框,因为这是窗口管理器的特殊情况

  • 为了获得并保持正确的大小,我使用MonitorFromWindow和GetMonitorInfo。位置和大小与样式更改(两种方式)一起应用,也在WM_大小处理程序中应用。观察WM_大小可以从外部恢复最小化还原事件,以及任务栏更改等

  • 由于未知原因,使用Win+箭头键移动不起作用。此问题仅在窗口处于最大化状态且没有标题时存在。使用此解决方法:

    • 在WM_WindowPos中,更改设置WS_标题样式。这允许窗口正确移动。之后,WM_大小处理程序再次应用正确的样式/位置/大小
    • 失败的方法:使用还原的窗口,而不是最大化。在这种情况下,在恢复移动最大化恢复生命周期中出错太多(恢复或最大化转到错误的监视器)

我不认为你真的想这么做。最大化窗口的行为与全屏窗口不同,试图让它们保持相同是非常痛苦的——用户可能会感到困惑——自Windows95发布以来,没有人成功。浏览器、媒体播放器和游戏都有全屏模式,这与最大化不同。当然,你需要自己的用户界面才能进入和离开全屏模式,但你所做的只是去掉所有的chrome浏览器,调整窗口大小,使其完全适合整个屏幕。所以我不应该保留窗口边框?这让事情变得简单多了。shell理解这种全屏窗口——如果一个窗口的大小正好能填满一个显示,当它是活动窗口时,shell会自动隐藏任务栏。Raymond Chen在他的博客上详细解释了这一点:我看到了oldnewthing的文章和所有的评论。