Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从左侧调整大小时窗口闪烁_C++_C_Winapi - Fatal编程技术网

C++ 从左侧调整大小时窗口闪烁

C++ 从左侧调整大小时窗口闪烁,c++,c,winapi,C++,C,Winapi,每当我同时移动窗口和调整大小时,我的窗口似乎都在闪烁。这通常发生在从窗口左侧调整大小时 为什么会发生这种闪烁?换句话说,当您重新定位窗口时,操作系统在做什么 注意:从右侧调整大小时,我没有体验到闪烁,这意味着窗口不一定会移动其原点X和Y。在Windows下调整窗口的大小涉及操作系统和窗口处理程序(用于窗口类的结构的lpfnWndProc成员)之间发送的多条消息。您可以使用一些消息监视工具自己发现它们。VisualStudio附带的就是这样一个工具 一条有趣的消息是:在调整窗口大小期间调用此消息,

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

为什么会发生这种闪烁?换句话说,当您重新定位窗口时,操作系统在做什么


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

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

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

  • 调整左边框或上边框的大小会导致复制旧窗口的内容以保留轴
  • 调整右下边框的大小不会复制任何内容,因为窗口的左上角没有移动
如果此默认复制与重新绘制期间放置视觉效果的方式不一致,则会导致闪烁。例如,在从左边框或上边框调整大小后,相对于右边框或下边框显示的所有内容都将错位:这些对象在调整大小后将不必要地移动,留下新旧混合的奇怪内容,因为只有未复制的像素将被重新绘制。如果你试图在WM_大小期间解决这个问题,你会得到闪烁(东西放错地方的时间间隔很短,但它仍然存在)

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

2018更新

WM\u NCCALCSIZE
WVR\u VALIDRECTS技巧仍然是防止Windows XP/Vista/7
SetWindowPos
执行不必要的导致闪烁的
BitBlt
的好方法

然而,微软再次这样做,在Windows 8/10上,DWM窗口管理器在传统的
SetWindowPos
BitBlt
上添加了另一层
BitBlt
,这可能会导致同样的问题,并且更难解决

有关不需要的
BitBlt
导致闪烁的原因的解释,以及
WM\u NCCALCSIZE
WVR\u VALIDRECTS
技巧的示例代码以及如何防止Windows 8/10 Aero执行相同操作的一些代码想法,请参阅:


原因是您正在移动整个窗口。Windows现在将在该特定位置重新绘制所有内容。从右侧收缩只会使其重新绘制边界。客户端区域不需要重新绘制,因为它刚刚被裁剪过。从右侧拉伸要求现在绘制未绘制的控件以及客户端区域。移动窗口需要重新绘制每个组件和客户端区域及其边界。@CantChooseServerNames我正在尝试将您所说的连接到此
SWP\u NOCOPYBITS
。但我认为它只是复制了一些信息。你用的是什么操作系统?启用主题的Windows XP(即默认情况下)不可避免地会闪烁。除Vista外,所有其他版本的Windows都正常。我还没试过Vista。回答得很好!接下来,当操作系统在从上到左调整大小时试图保留轴心时,是否会拉伸旧版本的内容?此外,操作系统似乎也在先移动,然后调整大小。你能证实吗?此外,我已经禁用了CS_HREDRAW和CS_VREDRAW,但仍然会出现闪烁。我们如何停止setPosWindow调用WM_PAINT?操作系统不会拉伸:它使用源和目标客户端区域宽度/高度中较短的一个进行复制。闪烁的另一个原因可能是由于将
WNDCLASSEX::hbrBackground
初始化为有效笔刷:在您有机会在WM_PAINT中重新绘制之前,使用它清除剩余区域。具有标志
SWP_NOREDRAW
,该标志应防止生成WM_PAINT和相关重绘消息。然后需要通过调用
invalidate
或直接绘制到窗口(带有或类似)来确保视图的一致性。