如何以原子方式更新HWND的样式和位置?

时间:2013-09-26 18:41:28

标签: c++ windows winapi

我正在编写一个Win7桌面应用程序,希望能够无缝地从窗口转换到窗口全屏(反之亦然),并且主要通过调用SetWindowLongPtr来立即更新其样式来完成此操作。 MoveWindow更新其大小和位置。问题是窗口闪烁一帧以显示其样式更新,但新的大小和位置未显示。下一帧看起来一切正确,但我试图避免这种单帧神器。

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

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

那么有没有办法调用这些API并让它们以原子方式直观地反映出来?作为奖励,将多个结果WM_SIZE消息合并为单个事件也很好,但我可以在消息处理程序中自行管理。

4 个答案:

答案 0 :(得分:2)

在Windows中执行此类操作非常困难,特别是因为Vista作为DWM会使事情复杂化。在您找到适合您的解决方案之前,这通常是一个反复试验的问题。

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);

答案 1 :(得分:1)

MSDN说:

  

某些窗口数据会被缓存,因此您需要进行更改   在致电SetWindowLongPtr后,SetWindowPos才会生效   功能

所以这个应该工作。也许尝试使用SetWindowPos而不是MoveWindow。

当你得到这些电话引起的事件时,你在窗口过程中做了什么有趣的事吗?特别是,你“修理”大小或类似的东西吗?

答案 2 :(得分:1)

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

答案 3 :(得分:0)

“windowed-fullscreen”是什么意思?是否与最大化相同?

如果是,ShowWindow (hwnd, SW_MAXIMIZE)