更改分辨率时如何保留其他应用程序窗口的大小和位置? (例如,以非桌面分辨率来回全屏游戏)

Posted

技术标签:

【中文标题】更改分辨率时如何保留其他应用程序窗口的大小和位置? (例如,以非桌面分辨率来回全屏游戏)【英文标题】:How to preserve other application windows sizes and positions when changing resolution? (eg. to and from full screen game in non-desktop resolution) 【发布时间】:2010-10-15 16:59:38 【问题描述】:

有没有人注意到使用 D3D 或 OpenGL 的应用程序在 Windows 中进入全屏时的这种奇怪行为?它仅适用于应用程序进入全屏然后切换回窗口或终止时。他们要么打乱其他应用程序的窗口位置(当我在单显示器机器上时),或者当我在多显示器机器上时将所有其他应用程序窗口移动到另一个屏幕。

如果没有应用程序没有显示这两个异常,我会认为这是理所当然的。那么,我的问题是,在编写应用程序以缓解这两个问题时,究竟需要注意什么?另外,不知道Windows以外的其他平台是否存在这个问题?

我的主要设置是 OpenGL/C++,但我认为这适用于您拥有的任何设置,因为它似乎是需要注意的平台 API。


编辑:好的,这里是对我观察的更多说明。即使在与桌面相同的分辨率下,问题仍然存在。所以,它似乎与分辨率切换无关,因为我已经看到应用程序/游戏即使它们与桌面的分辨率不同,当它们切换回来时,桌面上的窗口也会恢复到以前的状态全屏应用程序已运行。


edit2:看起来是分辨率切换问题,Windows(至少是 XP)似乎不记得应用程序窗口的位置和大小(在多显示器设置的情况下)。看起来唯一的解决方案是我在对问题的回答中提供的解决方案——即使它看起来像是操作系统应该提供的东西,至少作为一个或两个 API 调用。我仍然不相信这是唯一的解决方案,一定有一种简单的方法可以优雅、轻松地恢复,不是吗?

【问题讨论】:

因为他们改变了分辨率? 【参考方案1】:

我不能说我 100% 确定您遇到的情况。不过,我猜这是因为大多数 D3D/OpenGL 游戏会在启动/关闭时出于性能原因更改您机器的分辨率。

您看到的那些没有随机移动窗口的可能不会更改分辨率,因为它们可能能够在您当前的设置下运行。

【讨论】:

好的,我已经对问题进行了更多说明。它似乎与分辨率无关,而更多地与恢复前后桌面/窗口大小和位置的“记忆”有关。【参考方案2】:

嗯,我已经对此进行了更多研究 - 看起来在更改分辨率后恢复所有正在运行的窗口大小和位置没有默认回退,因此必须在应用程序中完成(至少在 XP 中)。

因此,为了从其他分辨率(例如全屏游戏)优雅地返回,我需要使用 EnumWindows 和适当的回调获取所有正在运行的应用程序 hWnd,并通过 GetWindowRect 将每个窗口 RECT 结构存储在列表中。 当切换回桌面分辨率时,我会再次 EnumWindows,但使用不同的回调设置每个正在运行的应用程序窗口的位置和大小,使用 SetWindowPos,使用我在切换到全屏之前保存的 RECT 列表。

当然,也有一些问题,比如只能通过 EnumWindows 等看到你得到一个窗口 hwnd。操作系统不提供这样的功能似乎很奇怪,即使只有 API。我想知道其他操作系统如何处理这个问题,如果他们处理它的话。

【讨论】:

【参考方案3】:

您不应该使用ChangedDisplaySettingsEx(..., CDS_FULLSCREEN, NULL) 吗?这将告诉系统分辨率交换是临时的。

【讨论】:

使用 CDS_FULLSCREEN 是处理此问题的正确方法。使用它不会改变其他窗口的位置和大小,甚至在进程退出时系统会自动恢复原来的显示模式。

以上是关于更改分辨率时如何保留其他应用程序窗口的大小和位置? (例如,以非桌面分辨率来回全屏游戏)的主要内容,如果未能解决你的问题,请参考以下文章

glutReshapeFunc() 没有做任何改变

如何随着分辨率的变化自动调整大小和调整表单控件

Pyglet:全屏时如何更改分辨率?

如何根据缩放、分辨率和窗口大小正确缩放网页?

更改 iPhone 方向时如何保持图像大小

如何在 Windows 窗体应用程序设置中记录窗口位置