带有alpha通道的闪烁儿童窗口

时间:2009-05-14 21:22:20

标签: c++ windows alphablending flicker doublebuffered

当绘制包含每像素alpha通道位图的子控件时,无论什么时候需要重绘,我们都会遇到很多闪烁。实际混合工作正常。我发现了很多关于减少闪烁的信息(例如this questionthis site),但我似乎找不到任何特别适用于这种情况的信息。

例如,我有一个带有几个不同位图的按钮,这些位图是alpha混合的,并且根据按钮的状态进入窗口。当他们的状态发生变化并且我需要绘制不同的位图时,我需要先重绘背景,否则它会与前一个状态的位图留下的像素混合在一起。这是我得到一些闪烁的地方,我偶尔会有一些背景撕裂。

通过让顶级父窗口绘制位图背景而不是纯色,以及使子控件重叠的可能性,问题变得更加复杂;只是将基础颜色乘以子项的位图是不可能的,就像使用WS_CLIPCHILDREN一样。

由于窗口有位图背景,我在true上返回WM_ERASEBKGND,以避免绘制只会被覆盖的颜色。

当然,双缓冲似乎可以解决所有这些问题,但我无法让它正常工作。我为顶级窗口设置了WS_COMPOSITED,为子窗口设置了WS_TRANSPARENT。当需要使用新位图重绘子窗口时,我遇到了一些问题(很可能是因为我不了解绘制顺序在这种情况下是如何工作的):

  • 如果我调用InvalidateRect()并传递子句柄,则会重新绘制子窗口,但不会重绘背景,因此像素会相互累积,混合在一起。
  • 如果我调用InvalidateRect()并传入句柄,并且矩形由子窗口的尺寸组成,则会重新绘制背景,但子窗口不会重新绘制。
  • 如果我同时执行上述两项操作,则会重新绘制背景以及子窗口,它看起来与我想要的完全一样 - 除非通过这样做,我已设法使其成为再次闪烁(这并不奇怪,因为这样两次调用InvalidateRect()似乎非常hackish,因为我猜每个调用可能导致缓冲区翻转,这违背了目的)。

我得出的结论是,我真的不明白我需要如何修改我的程序以处理双缓冲,或者双缓冲甚至可以帮助解决这种情况。我觉得它肯定会,但我不太明白我需要修改一些东西才能让一切都好好再玩。

2 个答案:

答案 0 :(得分:2)

您使用的是layered windows吗?如果不是,可以尝试一下。

同样适用于双缓冲consider this technique

答案 1 :(得分:1)

这可能完全偏离了基础 - 我很久以前的gui日......

但是你不能为你的不同状态预先计算混合物吗?我假设你的按钮可以启用/禁用和上/下,所以这只有4种组合。为什么不预先计算组合的位图?

或者已经合并的位图与现有状态的交互是否存在问题?