2

我正在编写一个 Win7 桌面应用程序,并希望它从窗口无缝过渡到窗口全屏(反之亦然),并且主要通过调用SetWindowLongPtr来更新其样式,然后立即调用MoveWindow来更新其大小和位置. 问题是窗口闪烁一帧以显示其样式已更新,但未显示新的大小和位置。下一帧一切看起来都正确,但我试图避免这种单帧伪影。

我尝试颠倒调用 API 的顺序,但它只是改变了工件的外观。我也尝试隐藏窗口,调用 API,然后显示窗口,但这只会导致窗口消失一帧。

我知道一种选择是创建一个具有所需属性的新窗口,然后销毁旧窗口,但我想找到一个更便宜的替代方案。

那么有什么方法可以调用这些 API 并让它们在视觉上原子地反映吗?作为奖励,将多个生成的 WM_SIZE 消息合并为一个事件会很好,但我可以在消息处理程序中自己管理它。

4

4 回答 4

2

在 Windows 中可靠地做这种事情是很困难的,特别是因为作为 DWM 的 Vista 会使事情复杂化。在找到适合您的解决方案之前,通常需要反复试验。

SetWindowPos有一个SWP_NOREDRAW标志防止窗口被重绘以响应调用。因此,您可以尝试先更改位置,然后更新样式,最后第三次调用以在新位置重绘窗口。例如,

SetWindowPos(hWnd, 0, x, y, w, h, SWP_NOREDRAW | SWP_NOZORDER);
SetWindowLongPtr(hWnd, GWL_STYLE, dwNewStyles);
RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_FRAME);
于 2013-09-26T20:18:31.263 回答
1

MSDN说:

某些窗口数据被缓存,因此您使用 SetWindowLongPtr所做的更改在调用SetWindowPos 函数之前不会生效。

所以这应该有效。也许尝试使用 SetWindowPos 而不是 MoveWindow。

当您收到由这些调用引起的事件时,您是否在窗口 proc 中做任何有趣的事情?特别是,您是否“固定”了尺寸或类似的东西?

于 2013-09-26T19:05:01.337 回答
1

退房WM_SETREDRAW;使用它来禁用重绘,更改窗口样式,然后调用RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN)以原子方式显示它们。

于 2013-09-26T19:51:37.537 回答
0

“全屏全屏”是什么意思?和最大化一样吗?

如果是这样,?ShowWindow(hwnd, SW_MAXIMIZE)

于 2013-09-26T18:53:55.107 回答