WinForms分层控件和背景图像导致滚动撕裂我有一个具有以下属性的窗体:现在所有控件都设置为DoubleBuffered,包括窗体本身。一切都按预期工作,除了滚动PictureBox的面板时,表单背景图像滚动,它重复显示垂直和水平撕裂,尽管它的静态图像适合表单的大小,当您停止滚动时它显示正确。这仅在拖动滚动条时发生,如果我单击滚动条中的任意点来移动它,它会正确显示。据我所知,双缓冲应该可以消除这种情况,但即使使用双缓冲,它也能起到同样的作用,也许稍微好一点,但在滚动时仍然是一个大问题。我尝试将所有控件放在另一个面板中,而不是使用窗体背景图像并将此面板放在窗体上,但这没有任何区别。您正在与一个名为“拖动时显示窗口内容”的Windows系统选项作斗争。它适用于所有现代版本的Windows。关闭它不是一个现实的目标,因为它是一个系统选项,会影响所有应用程序的所有窗口。没有后门可以选择性地绕过这个选项。启用后,操作系统会优化窗口的滚动。它会快速执行bitblt操作以移动视频帧缓冲区中的像素,并仅为滚动的窗口部分生成绘制消息。向下滚动时,它就像最下面的几行像素。底层winapi调用是ScrollWindowEx()。目标是为应用程序提供响应速度更快的UI,实现滚动的工作量要少得多。您可能会看到它的去向,ScrollWindowEx()还移动由窗体的BackgroundImage绘制的像素。你可以看到。接下来您会看到优化绘制的副作用,它只会重新绘制显示的窗口部分。因此移动的背景图像像素不会重新绘制。看起来像“涂抹”效果。有一个简单的解决方法,只需为面板的滚动事件实现一个事件处理程序并调用Invalidate()。所以整个面板再次重新绘制:privatevoidpanel1_Scroll(objectsender,ScrollEventArgse){panel1.Invalidate();但是现在你会注意到,paintsideeffect不再被优化。您仍然会看到像素被移动然后透支。这有多明显取决于BackgroundImage的绘制成本。通常从不便宜,因为它没有最好的像素格式(32bppPArgb),并且没有合适的大小,因此需要重新缩放以适合窗口。视觉效果类似于“pogo”,面板的一个边缘快速摇晃。您不太可能会发现它可以接受或想要完成优化BackgroundImage的工作。阻止ScrollWindowEx()完成其工作需要一个非常强大的武器,您可以使用LockWindowUpdate()对其进行调整。像这样:使用System.Runtime.InteropServices;...privatevoidpanel1_Scroll(objectsender,ScrollEventArgse){if(e.Type==ScrollEventType.First){LockWindowUpdate(this.Handle);}else{LockWindowUpdate(IntPtr.Zero);panel1.Update();如果(e.Type!=ScrollEventType.Last)LockWindowUpdate(this.Handle);}}[DllImport("user32.dll",SetLastError=true)]privatestaticexternboolLockWindowUpdate(IntPtrhWnd);效果很好,背景图像像素现在非常稳定。任何其他像素,嗯,不是那么多。另一种视觉效果,我们称之为“皱纹”。可以通过将窗口置于合成模式来摆脱该工件。哪个双缓冲整个窗口表面,包括子控件:protectedoverrideCreateParamsCreateParams{get{constintWS_EX_COMPOSITED=0x02000000;varcp=base.CreateParams;cp.ExStyle|=WS_EX_COMPOSITED;返回cp;唯一剩下的神器是这不是非常廉价代码的副作用。滚动时看起来可能不那么流畅。否则它会告诉你为什么28年前窗户被设计成不透明的。以上是C#学习教程:WinForms分层控件和背景图片导致滚动时撕裂。代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
