问题:当我抓住我的Windows应用程序的调整大小边框,特别是顶部或左边框,并调整窗口大小时,窗口的内容会在我拖动时调整"实时"大小,但是它们会以一种看似像的丑陋方式调整大小即使是最新手的用户也是一个明显的错误:窗口相对边缘的内容从边缘拖动抖动/闪烁/来回跳跃.视情况而定,现象可能如下:
一旦我停止拖动,丑陋的现象就会停止,但在拖动过程中,它会使应用程序看起来很业余和不专业.
说这个Windows问题已经让成千上万的应用程序开发人员疯狂,这并不是轻描淡写的.
以下是现象,友好地准备了两个实例图片一个相关的问题由罗马Starkov:


另一个例子展示了Kenny Liu的邪恶"双重图像"现象(请注意快速闪光):

有关任务管理器现象的另一个示例视频就在这里.
这个问题的目的: 任何遇到这个问题的开发人员都会发现至少有30个StackOverflow问题,其中一些是最近的,有些是从2008年开始的,充满了很有希望的答案很少有效.现实情况是,这一个问题有很多原因,而现有的StackOverflow问题/答案从未使更广泛的背景清晰.这个问题试图回答:
本问题的范围:对于StackOverflow问题的范围,这种现象发生在:
请勿标记为广泛或DUP:在标记为复制或标记为广泛之前,请阅读以下完整答案.我们已经经历了这个循环,SO用户在理解了以下内容之后经常重新打开这个问题:这个问题有益于社区,是第一个解释窗口调整大小抖动的所有不同原因的问答,以便用户可以识别哪个原因导致他们的问题并解决它.下面的答案很长,只是因为解释为什么一般发生抖动是很棘手的,不是因为这个问题涵盖了许多单独的问题和问题,这些错误/问题可以通过单独的问答得到更好的服务.正如您将看到的,上面的所有排列(本机/托管,窗口/对话框,XP-10)都归结为只有两个根本原因,但识别您所拥有的是棘手的部分.这就是这个问题的意义所在.将问题分开将完全否定这一好处.我们在下一节中进一步限制了问题的范围......
不在本问题的范围内:
如果您的应用程序有一个或多个子窗口(子HWND),则此问题中的信息对您很有用(因为BitBlts我们将描述的引起混蛋的内容与父窗口一起应用于您的子窗口),但在窗口调整大小时还有另外一个问题需要处理,这超出了这个问题的范围:你需要让你的所有子窗口以原子方式移动并与父窗口同步.对于这项任务,你可能会想要 BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos,你可以在这里和这里找到它们.
这个问题假设如果你的应用程序使用GDI,DirectX或OpenGL绘制到一个窗口,那么你已经WM_ERASEBKGND在你的应用程序中实现了一个wndproc简单的返回1. WM_ERASEBKGND是来自Windows 3.1的一个神秘的Windows残余,以前WM_PAINT给你的应用程序一个机会在你画窗户之前"擦掉窗户的背景"......嗯.如果你让WM_ERASEBKGND消息进入DefWindowProc(),那将导致你的整个窗口在每次重绘时被涂成纯色,通常是白色,包括在实时窗口大小调整期间发生的重绘.结果是一个丑陋的全窗口闪烁是粗略的,但不是我们在这个问题中讨论的抖动/闪烁/跳跃的类型.拦截WM_ERASEBKGND立即解决了这个问题.
此问题主要是通过使用鼠标拖动窗口边框来实时调整大小.但是,此处编写的大部分内容也适用于当应用程序手动执行一次性窗口调整时可以看到的丑陋工件SetWindowPos().这些不太明显,因为它们只在屏幕上轻弹一瞬间,而不是长时间的拖动.
这个问题不是关于如何使你的特定于应用程序的绘图代码更快,即使这样做可能是许多情况下丑陋的调整大小问题的解决方案.如果您的应用确实需要花费大量时间在实时窗口调整大小期间重新显示其内容,请考虑优化绘图代码,或者至少在调整大小期间切换到更快,质量更低的绘图模式,方法是拦截WM_ENTERSIZEMOVE/WM_EXITSIZEMOVE消息以检测调整大小.
如果您的应用程序在应用程序调整大小期间根本无法调整大小(例如,在调整大小期间它"挂起",特别是如果它是使用GLFW或其他库的OpenGL),请参阅这些其他问题,这些问题解释了WM_SYSCOMMAND在拖动过程中Microsoft内部隐藏的嵌套/模态事件循环:这里特别是这个好的答案,这里,这里 …