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

Nmd*_*ery 5 c++ windows directx direct3d dxgi

DXGI的MSDN页面提供了有关如何处理与桌面分辨率不同的全屏分辨率的说明.它说要在打电话IDXGISwapChain::ResizeTargets()之前打电话IDXGISwapChain::SetFullscreenState()以防止闪烁等等.

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

Ant*_*eru 7

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

"正确"的答案是手动处理Alt + Enter.所以,禁用Alt + Enter使用MakeWindowAssociation并弄脏你的手.首先,没有必要捕获WM_SIZE.相反,监听WM_ENTERSIZEMOVE,WM_CAPTURECHANGED,WM_WINDOWPOSCHANGEDWM_EXITSIZEMOVE.这将阻止您必须处理WM_SIZE并仍然获得所有相关的窗口大小调整事件.(执行此操作时,请同时阅读此问题:WM_ENTERSIZEMOVE/WM_EXITSIZEMOVE - 使用菜单时,并不总是配对)

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

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

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