正确处理Alt-Enter / Alt-Tab全屏分辨率

时间:2014-08-18 17:52:25

标签: c++ windows directx direct3d dxgi

The MSDN page on DXGI提供了有关如何处理与桌面分辨率不同的全屏分辨率的说明。它表示在致电IDXGISwapChain::ResizeTargets()之前致电IDXGISwapChain::SetFullscreenState()以防止闪烁,等等。

它没有说明如何处理Alt-Enter,它在程序有机会自己调用IDXGISwapChain::SetFullscreenState()之前调用IDXGISwapChain::ResizeTargets()。如果在WM_SIZE消息上调用后一种方法,则将发送另一条WM_SIZE消息,可能导致无限循环。当按下alt-enter或alt-tab时,如何确保后者在前者之前被调用,并且模式切换一般无痛地发生?

2 个答案:

答案 0 :(得分:7)

这将是非常棘手的......正确的处理方式是IDXGIFactory::MakeWindowAssociation,据我所知,没有人能成功使用。无论如何你可能想尝试一下。

“正确”的答案是手动处理Alt + Enter。因此,请使用MakeWindowAssociation禁用Alt + Enter并弄清楚。首先,没有必要捕获WM_SIZE。相反,请倾听WM_ENTERSIZEMOVEWM_CAPTURECHANGEDWM_WINDOWPOSCHANGEDWM_EXITSIZEMOVE。这将阻止您处理WM_SIZE并仍然获得所有相关的窗口大小调整事件。 (在执行此操作时,请同时阅读此问题:WM_ENTERSIZEMOVE / WM_EXITSIZEMOVE - when using menu, not always paired

好的,假设一切正常,对于Alt + Enter,您必须执行以下操作:使用IDXGISwapChain::SetFullscreenState将交换链设置为全屏,然后调整交换链的大小(IDXGISwapChain::ResizeBuffers) 。默认情况下,在调整大小之前,您将获得一个尽可能接近窗口当前分辨率的交换链。正确执行此操作的方法是首先枚举全屏分辨率,并在全屏显示时强制执行您想要的分辨率。这听起来很丑陋,但它似乎是解决问题最有力的方法。

一般来说,真正独有的全屏模式不值得麻烦,因为当有人进入Alt + Tab时你总是会闪烁(如果发生模式切换你就无法避免它,因为屏幕本身必须重新调整。)更好的解决方案是使用全屏无边框窗口。您只需创建一个没有任何装饰的窗口类,使其全屏,将其放置以覆盖整个屏幕并完成它。然后你根本不用担心Alt + Enter和Alt + Tab。它还允许人们继续在第二个屏幕上工作而不会闪烁。性能方面,这是非常好的(大多数新游戏支持这种“无边界全屏”。)

可能有一颗银弹可以正确解决所有问题,但我还没有看到它。如果有一个更清洁/更好的解决方案,我会很好奇听到它。 “无边框全屏”似乎是目前的标准,但IIRC,Unity 5只允许Direct3D 11使用“无边框全屏”。

答案 1 :(得分:1)

我只想添加一个关于这个问题的更新 - 我已经编写了一个小窗口库,我相信它可以很好地处理DXGI - 没有调试消息,没有错误消息,并且一切都按预期运行,至少在我的Windows环境。这个问题的完整解决方案太复杂了,无法在单个答案中解释,因为它需要大量精确放置的方法调用(DXGI实际上非常严格,但事实证明),但是我的代码在{{3如果有人想看看它。具体来说,githubthis file是您要查看的内容 - 后者是前者的聚合对象。

请注意,我已禁用 ALT + ENTER 以支持 F11 ,但功能完全相同。

顺便说一下,如果你想使用那个库,我将把它作为免费软件发布,并尽快提供文档。