【问题标题】:Flickering on window when resizing from left side从左侧调整大小时在窗口上闪烁
【发布时间】:2014-01-24 08:45:35
【问题描述】:

当我同时移动窗口和调整大小时,我的窗口似乎在闪烁。这通常发生在从窗口左侧调整大小时。

为什么会出现这种闪烁?换句话说,当你重新定位一个窗口时,操作系统在做什么?

注意:从右侧调整大小时我没有遇到闪烁,这意味着窗口不一定会移动其原点 X 和 Y。

【问题讨论】:

  • 原因是因为您要移动整个窗口。 Windows 现在将重绘该特定位置的所有内容。从右侧缩小只会使其重新绘制边界。客户区不需要重新绘制,因为它只是被裁剪了。从右侧拉伸要求现在将绘制任何未绘制的控件以及客户区域。移动窗口需要重新绘制每个组件和客户区及其边框。
  • @CantChooseUsernames 我正在尝试将您所说的内容与SWP_NOCOPYBITS 联系起来。但我认为它只是将这些位复制过来。
  • 您使用的是什么操作系统?启用主题(即默认)的 Windows XP 不可避免地会出现闪烁。除了 Vista 之外的所有其他版本的 Windows 都可以。我没试过 Vista。

标签: c++ c winapi


【解决方案1】:

在 Windows 下调整窗口大小涉及在操作系统和窗口处理程序之间发送的几条消息(WNDCLASSEX 结构的 lpfnWndProc 成员用于register 窗口类)。您可以使用一些消息监控工具自己发现它们。 Visual Studio 附带的Spy++ 就是这样一种工具。

一个有趣的消息是WM_NCCALCSIZE:此消息在窗口调整大小期间调用,可以生成两个矩形(当设置 WVR_VALIDRECTS 标志时):源和目标指定旧窗口客户区的哪些内容可以在新窗口的位置。默认情况下,它假定左上角是一个枢轴:

  • 调整左边框或上边框的大小会导致复制旧窗口的内容以保留枢轴;
  • 调整右下边框的大小不会复制任何内容,因为窗口的左上角没有移动。

此默认复制可能会导致闪烁,如果它与您在重绘期间定位视觉效果的方式不对应。例如,相对于右或下边框显示的所有内容在从左或上边框调整大小后都会错位:这些对象将不必要地移动,在调整大小后留下新旧事物的奇怪混合,因为只有未复制的像素将被重新粉刷。如果您尝试在 WM_SIZE 期间使用InvalidateRect 来解决混乱,您会得到闪烁(东西放错位置的时间间隔很短,但仍然存在)。

禁用此行为的最简单方法是为您的窗口设置 CS_HREDRAW 和 CS_VREDRAW Class Styles

【讨论】:

  • 很好的答案!跟进,操作系统在从顶部和左侧调整大小时尝试保留枢轴时是否会拉伸旧的内容?此外,操作系统似乎也在先移动然后调整大小。你可否确认?另外,我已经禁用了 CS_HREDRAW 和 CS_VREDRAW 并且仍然面临闪烁。
  • 我们怎样才能阻止 setPosWindow 调用 WM_PAINT?
  • 操作系统不会拉伸:它使用源和目标客户区宽度/高度中较短的一个进行复制。闪烁的另一个原因可能是由于将 WNDCLASSEX::hbrBackground 初始化为有效的画笔:WM_ERASEBKGND 在您有机会在 WM_PAINT 中重新绘制之前使用它来清除剩余区域。
  • SetWindowPos 有标志SWP_NOREDRAW 应该防止生成 WM_PAINT 和相关的重绘消息。然后,您需要通过调用InvalidateRect 或直接绘制到窗口(使用GetDC 或类似方法)来确保一致的视图。
  • 这个答案可能给出了正确的理论,但给出了错误的解决方案。当您通过左边框调整窗口大小时,设置 CS_HREDRAW|CS_VREDRAW 不会阻止窗口闪烁。 NonNumeric 的建议也是错误的,避免使用 hbrBackground 画笔或从 WM_ERASEBKGRND 返回 true 不会停止问题。
【解决方案2】:

2018 年更新。

WM_NCCALCSIZEWVR_VALIDRECTS 技巧仍然是防止 Windows XP/Vista/7 SetWindowPos 执行导致闪烁的不必要的 BitBlt 的好方法。

但是,Microsoft 再次这样做了,在 Windows 8/10 上,DWM 窗口管理器在旧的 SetWindowPos BitBlt 之上添加了另一层 BitBlt,这可能会导致相同的问题并且更难解决.

有关不需要的 BitBlt 导致闪烁的原因的解释,以及 WM_NCCALCSIZE WVR_VALIDRECTS 技巧的示例代码以及如何防止 Windows 8/10 Aero 这样做的一些代码想法,请参阅:

How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?

【讨论】:

    猜你喜欢
    • 2022-10-13
    • 1970-01-01
    • 2018-07-27
    • 2014-12-29
    • 2016-03-19
    • 2015-08-29
    • 2019-02-27
    • 2012-11-17
    • 1970-01-01
    相关资源
    最近更新 更多