将监视器B中的窗口移动到监视器B上时双监视器设置中监视器A的全屏模式中断

时间:2015-08-16 14:51:24

标签: c++ winapi fullscreen multiple-monitors direct3d11

我正在构建一个Win7 / 8/10 x64 Direct3D11桌面应用程序,允许用户在窗口模式和全屏模式之间切换(适当的专用全屏模式,而不仅仅是最大化的窗口*)。在双显示器设置上,我遇到了一些问题。

交换机本身是使用IDXGISwapChain::SetFullscreenState手动执行的,并按预期工作:占据狮子窗口区域份额的监视器(让我们称之为监视器A)进入专用全屏模式,同时离开另一个(监视器B),允许用户正常与B上的窗口以及A上的全屏应用程序进行交互。

但是,如果拖动或调整B上的窗口以使其跨越到A,则应用程序的全屏状态会受到干扰:有时它会恢复到窗口模式(使应用程序内部保持不变)跟踪变量不同步),有时它保持在准全屏模式,它似乎拒绝进一步的模式切换,等等。如果在应用程序进入全屏模式之前与A和B重叠的窗口获得焦点,则会发生同样的情况。

有什么方法可以阻止这种情况吗?

我希望操作系统能够尊重我的应用程序的专用全屏模式,并将其保持在稳健状态,即使其他窗口被拖动到该监视器上也是如此。我希望这种行为类似于拥有一个"始终在线,最大化的无边界窗口"取而代之的是,只有其他窗户就会消失在其后面。#34;并且根本不会影响我的全屏窗口的状态。

我尝试了一些解决方法,例如回复WM_KILLFOCUS并暂时将我的应用程序切换到" maximixed无边框窗口"直到它再次收到WM_SETFOCUS,但WM_KILLFOCUS消息有一个延迟,在此期间用户有时间将另一个窗口拖动到仍处于全屏模式的区域,从而使我恢复正常之一。

*我想要这个功能而不是简单地使用最大化的无边界窗口(也是支持模式,顺便说一句)的原因与它有关,允许更低的鼠标移动到渲染延迟,vsync控制(ON / OFF)等......所有这些 - 简而言之 - 对于这个应用程序的性质非常重要(这不是游戏)。

1 个答案:

答案 0 :(得分:2)

虽然不理想(理想会有一种方法让操作系统本身正确处理),但我找到了一个合理的解决方法,我想我现在可以忍受。这是问题中提到的概念的变体(" ...就像响应WM_KILLFOCUS并暂时将我的应用程序切换到最大化的无边界窗口..."),但没有严重的延迟问题:

每当应用程序进入专用全屏模式时,它也会通过调用SetCapture来捕获鼠标。这不会影响用户与监视器B上的其他窗口进行交互的能力,但它确保任何此类de / activate交互 - 如在另一个应用程序中单击鼠标 - 将发送在之前,WM_LBUTTONDOWN到我的应用程序会失去焦点。重要的是,这会立即发生 ,与具有显着延迟的WM_KILLFOCUS消息不同。

当收到这样的WM_LBUTTONDOWN消息时(全屏显示),应用程序会检查点击是否发生在屏幕区域之外。如果是这样,这意味着它将失去焦点,从而使自己暴露于原始问题中提出的所有复杂情况。因此它暂时退出专用的全屏模式,并且"取代"它具有(视觉上相同的)无边框最大化窗口。当应用程序重新获得焦点时,它将重新进入专用的全屏幕。

这很好用,因为当你还没有与之交互时,你并不真正关心应用程序的响应能力。这里最大的不便是在这些焦点转移时发生的模式切换闪烁,但考虑到替代方案,我发现为我想要完成的事情付出的代价是可以接受的(但无论如何 - 我会非常对更好的解决方案感兴趣。)

编辑1:值得注意的是,由于应用程序有其他方式失去焦点而不是通过鼠标点击,WM_KILLFOCUS 处理。

编辑2:我最近意识到处理WM_BUTTONDOWN消息是多余的。仅SetCapture就可以确保快速收到WM_KILLFOCUS消息。