我正在构建一个Win7 7/8/10 x64 Direct3D11桌面应用程序,它允许用户切换窗口模式和全屏模式(适当的专用全屏模式,而不仅仅是最大化窗口*)。在双监视器设置上,我遇到了一些问题。
开关本身是使用IDXGISwapChain::SetFullscreenState手动执行的,并按预期工作:容纳窗口大部分区域(我们称之为监视器A)的监视器进入专用全屏模式,而另一个(监视器B)保持原样,允许用户正常地与B上的窗口以及A上的全屏应用程序进行交互。
但是,如果B上的窗口被拖动或调整大小,使其跨越到A,则应用程序的全屏状态会受到干扰:有时它只是返回到窗口模式(使应用程序的内部跟踪变量不同步),有时它停留在准全屏模式,它似乎拒绝进一步的模式切换,依此类推。如果在应用程序进入全屏模式之前,A和B重叠的窗口获得焦点,也会发生同样的情况。
有什么办法可以防止这种情况吗?
我希望操作系统能够尊重我的应用程序专用的全屏模式,即使其他窗口被拖到监视器上,也希望它保持在一个健壮的状态。我希望这种行为类似于有一个“总是在顶部,最大限度的无边界窗口”代替,即让其他窗口只是“消失在它后面”,而不影响我的全屏窗口的状态。
我尝试了一些解决方法,比如响应WM_KILLFOCUS,暂时将我的应用程序切换到一个“最大化无边界窗口”,直到它再次接收到WM_SETFOCUS为止,但是WM_KILLFOCUS消息有一个滞后,在此期间,用户有时间将另一个窗口拖到仍然处于全屏模式的区域,从而使我回到正方形。
*我之所以想要这个特性,而不是简单地使用一个最大化的无边界窗口(这也是一个支持的模式,顺便说一句),是因为它允许更低的鼠标移动到渲染延迟,vsync控制(开/关)等等。总之,所有这些都对这个应用程序的性质很重要(这不是一个游戏)。
发布于 2015-08-17 19:24:07
虽然不太理想(理想的是有办法让操作系统自己正确地处理这个问题),但我已经找到了一个合理的解决办法,我想我现在可以接受。这是问题("..like响应WM_KILLFOCUS并暂时将我的应用程序切换到最大的无边界窗口.“)中提到的概念的一个变化,但没有严重的延迟问题:
每当应用程序进入专用全屏模式时,它也会通过调用SetCapture来捕获鼠标。这不会影响用户与监视器B上的其他窗口进行交互的能力,但它将确保任何这样的去/激活交互--就像在另一个应用程序中单击鼠标--在失去焦点之前将WM_LBUTTONDOWN发送到我的应用程序。重要的是,这是立即发生的,不像具有显著延迟的WM_KILLFOCUS消息。
当接收到这样的WM_LBUTTONDOWN消息时(在全屏时),应用程序将检查该单击是否发生在其屏幕区域之外。如果是这样的话,这意味着它将失去焦点,从而暴露出原来问题中提出的所有复杂问题。因此,它暂时退出专用的全屏模式,并用一个(视觉上相同的)无边界最大化窗口“替换”它。当应用程序重新获得焦点时,它会返回到专用的全屏。
这很好,因为当您不与应用程序交互时,您并不真正关心应用程序的响应性。这里最大的不便是发生在这些焦点转移上的模式切换闪烁,但考虑到替代方案,我发现为我想要完成的事情付出的代价是可以接受的(但无论如何,我会非常感兴趣的一个更好的解决方案)。
编辑1:值得注意的是,由于应用程序除了通过鼠标单击之外还有其他失去焦点的方法,所以WM_KILLFOCUS也会被处理。
编辑2:我最近意识到处理WM_BUTTONDOWN消息是多余的。仅使用SetCapture就可以确保足够快地接收到WM_KILLFOCUS消息。
https://stackoverflow.com/questions/32036388
复制相似问题