带 Alpha 通道的闪烁子窗口
当绘制包含具有每像素 Alpha 通道的位图的子控件时,每当需要重新绘制它们时,我们都会遇到大量闪烁。 实际混合工作正常。 我发现了很多有关减少闪烁的信息(例如这个问题或此网站),但我似乎找不到任何专门适用于这种情况的内容。
例如,我有一个带有几个不同位图的按钮,这些位图根据按钮的状态进行 alpha 混合并位图传输到窗口。 当它们的状态发生变化并且我需要绘制不同的位图时,我需要首先重新绘制背景,否则它会与前一个状态位图留下的像素混合。 这是我遇到一些闪烁的地方,我偶尔会看到一些背景撕裂的地方。
通过让顶级父窗口绘制位图背景而不是纯色,以及子控件重叠的可能性,问题变得更加复杂; 仅仅将底层颜色乘以子级的位图是不可能的,就像使用 WS_CLIPCHILDREN 一样。
由于窗口具有位图背景,因此我在 WM_ERASEBKGND
上返回 true
,以避免绘制将被覆盖的颜色。
当然,双缓冲似乎可以解决所有这些问题,但我无法让它正常工作。 我为顶级窗口设置了 WS_COMPOSITED
,为子窗口设置了 WS_TRANSPARENT
。 当需要使用新位图重绘子窗口时,我遇到了一些问题(很可能是因为我不理解绘制顺序在这种情况下是如何工作的):
- 如果我调用
InvalidateRect()
并传递子句柄,子窗口确实被重绘,但背景没有重绘,因此像素相互堆积,混合在一起。 - 如果我调用
InvalidateRect()
并传入 parent 句柄,以及由子窗口尺寸组成的矩形,则背景将被重绘,但子窗口不会。 - 如果我执行上述两项操作,那么背景和子窗口都会被重新绘制,并且它看起来完全符合我的要求 - 除了通过这样做,我设法使其闪烁 em> 再次(这并不奇怪,因为像这样调用
InvalidateRect()
两次似乎非常黑客,因为我猜测每次调用可能会导致缓冲区翻转,这会失败目的)。
我得出的结论是,我真的不明白我需要如何修改我的程序来处理双缓冲,或者双缓冲是否有助于解决这种情况。 我觉得肯定会的,但我不太明白我需要如何修改才能让一切再次正常运行。
When drawing child controls containing bitmaps with per-pixel alpha channels, we are getting quite a lot of flickering whenever they need to be redrawn. The actual blending is working correctly. I've found a lot of info about reducing flicker (such as this question or this site), but I can't seem to find anything that applies specifically to this situation.
For example, I've got a button with a few different bitmaps that are alpha blended and blitted to the window, depending on the state of the button. When their state changes and I need to draw a different bitmap, I need to redraw the background first, or else it blends with pixels left over from the previous state's bitmap. This is where I am getting some flickering, where I get a bit of the background tearing in occasionally.
The problem is made more complicated by having the top-level parent windows drawing a bitmap background, rather than a solid color, along with the possibility of having child controls overlapping; just multiplying the underlying color into the child's bitmap is out of the question, as is using WS_CLIPCHILDREN
.
Since the windows have a bitmap background, I'm returning true
on WM_ERASEBKGND
, to avoid drawing a color that will just be overwritten.
Of course, double buffering would seem to solve all of this, but I have not been able to get it to work right. I've set WS_COMPOSITED
for top-level windows, and WS_TRANSPARENT
for child windows. When it comes time to redraw a child window with a new bitmap, I am having a few issues (most likely from me not understanding how the draw order is working in this situation):
- If I call
InvalidateRect()
and pass the child handle, the child window is indeed redrawn, but the background is not redrawn, and so the pixels accumulate on top of each other, blending together. - If I call
InvalidateRect()
and pass in the parent handle, with a rectangle consisting of the child window's dimensions, the background is redrawn, but the child window is not. - If I do both of the above, then the background is redrawn as well as the child window, and it looks exactly as I'd want -- except that by doing so, I've managed to make it flicker again (which isn't really surprising, since it seems terribly hackish to call
InvalidateRect()
twice like that, as I'd guess that each call is probably causing the buffers to flip, which defeats the purpose).
What I've come to conclude is that I don't really understand how I need to modify my program to handle double buffering, or if double buffering will even help with this situation. I feel like it definitely would, but I don't quite understand how I need to modify things to get everything to play nicely again.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能完全不对劲——我的 GUI 时代已经是很久以前的事了……
但是你不能预先计算不同状态的混合吗? 我假设你的按钮可以启用/禁用和向上/向下,所以只有 4 种组合。 为什么不预先计算组合位图?
或者问题是已经组合的位图与现有状态的交互?
This could be completely off base - my gui days were a long long time ago...
But couldn't you just precompute the blends for your different states? I assume your button can be enabled/disable and up/down, so that's only 4 combinations. Why not precompute the combined bitmaps?
Or is the problem the interaction of already combined bitmaps with the existing state?
您是否使用分层窗口? 如果没有的话也许可以尝试一下。
另外,对于双缓冲考虑这种技术。
Are you using layered windows? If not maybe try it out.
Also for double buffering consider this technique.