窗口区域、移动子项、DWM及其可能创建的白色块状混乱问题。

3

背景:我有一个顶级窗口,其中定义了一个区域(使用SetWindowRgn()创建),并且我有一个子元素,通过SetWindowPos()移动,使其一些像素与父窗口的裁剪部分重叠。

结果:这些像素变成了完全不透明、完全白色的像素,而不是保持完全透明(因为它在其父窗口的区域之外)。这并不是子窗口在不应该绘制时被绘制了,因为无论子窗口看起来如何,这些冒犯的像素都是白色的。

下面,小的橙色子窗口已经沿着父窗口的边缘移动了一些。这只会发生在具有透明窗口区域的边缘上(因此白色像素始终限制在父窗口的最大矩形内)。

enter image description here

如果隐藏然后显示父窗口,情况就会得到纠正(仅使其无效并强制重新绘制不会清除白色像素)。

这在Vista和7上都被观察到。如果我禁用桌面窗口管理器(DWM),这种行为就会消失。在某些情况下,更新图形驱动程序后也会消失。也许它与这个问题有关吗?:Vista live thumbnail issue with SetWindowRgn。我最初只是打算将其归档为一种罕见的错误,但它已经出现了足够多的次数,值得更多的审查。

还有其他人遇到过这个问题吗?DWM和窗口区域如何相互作用的任何见解?

此外,我知道我可以为每个应用程序禁用DWM,但这会在应用程序运行时禁用它,除了在启动和关闭时导致屏幕闪烁之外,这并不是一个更好的问题。


你尝试过在另一台图形卡(独立机器)上吗?此外,您是否确保正确地在绘画中使用了alpha通道? - Martyn Lovell
这实际上是在没有任何Alpha通道的情况下,因为我已经简化了事情以缩小原因范围;测试中唯一的透明度来自窗口区域。我已经在相当多的机器上尝试过它,其中大多数机器都没有出现这个问题 - 只有少数机器实际上存在这个问题,但对于这些机器每次重现都是可行的。 - Doug Kavendek
所有出现故障的机器是否都有相同的显卡制造商?根据您提供的信息,我强烈怀疑是视频驱动程序的错误。 - Martyn Lovell
这里有两台机器存在相同问题,它们似乎拥有不同的显卡;一台是“移动英特尔965”,另一台是集成的“英特尔高清图形”。尽管其中一台只是CPU的一部分,而另一台则是独立的离散显卡,但Intel是它们的共同点。 - Doug Kavendek
1个回答

1

我不喜欢再次回答自己的问题,但我找到了一个解决方法。我发现重新设置窗口区域可以清除任何杂散的白色像素,而不会在其他地方引起任何丑陋的重绘或闪烁。即使我设置的区域与现有区域相同,这也是有效的,因此像这样简单的操作就可以解决问题:

HRGN hRgn = CreateRectRgn(0,0,0,0);
GetWindowRgn( hWnd, hRgn );
SetWindowRgn( hWnd, hRgn, true );
DeleteObject( hRgn );

作为额外的奖励(或者说是这个问题的另一个奇怪方面),如果我在移动窗口之前不久调用它,那么白色像素中就没有任何一个显示出来,但为了保险起见,在任何窗口的平移动画之前和之后都要执行此步骤。

可能问题的根源在于我在创建窗口后将其置于某种状态,该状态通过重新设置区域得到清除。知道根本原因会很好,但由于这感觉像是在解决驱动程序错误,也许我永远不会知道根本原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接