我在按钮上放了一个GIF动画。它的动画效果很好(大部分时间:P)但是当重新绘制(重新绘制)窗口时,动画会停止。我试图在处理Paint事件时刷新按钮(button.Refresh()),但它没有解决问题。 \
任何人都知道如何解决这个问题?
答案 0 :(得分:3)
也许我错了,但我认为问题在于它不会在重绘表单时停止动画,而是在动画对象被另一个窗口遮挡时停止。这是预期的行为;问题在于,在Windows Vista和Windows 7中,显示是合成的,所以即使窗口被“遮挡”,它也永远不会被遮挡,并且在不被遮挡的情况下它将永远不会收到油漆消息,这将使动画重新进入。
此错误似乎会影响任何带有动画对象的ButtonBase派生控件。
问题是Control.IsWindowObscured功能。它会返回true。你可以在ButtonBase.cs文件中看到,在System.Windows.Forms.ButtonBase.OnFrameChanged中,最后有一行代码说:
if (IsWindowObscured) {
StopAnimate();
return;
}
其中存在问题。
仅供参考,从ImageAnimator线程调用OnFrameChanged。这是ImageAnimator.Animate(image,eventhandler)中指定的回调。 ButtonBase在私有void Animate(bool animate)函数中设置它。 ImageAnimator线程每50ms轮询一次,并检查它正在监视的任何图像是否需要一个新帧。如果是这样,它设置一个标志以使控件无效并绘制新帧。
由于我们无法访问,因此我认为我们无法做到这一点。作为一种解决方法,我在我的表单中实现了一个计时器,该计时器每500毫秒使控件无效,因此如果先前已经停止,它将强制它重新启动。我们无法覆盖甚至访问它是非常烦人的。我担心唯一的解决方案是上面的黑客攻击,或创建或使用自己或第三方创建的控件。
澄清 - 这只是使用桌面组合的Windows Vista或Windows 7上的问题。问题是窗口永远不会真正模糊,就像它们不使用桌面组合时一样。它们总是由窗口管理器缓冲。 (Windows 2000+中有特殊的分层窗口,但暂时忽略它)。以前,如果窗口的某些部分不在屏幕上或被另一个窗口遮挡,则它们不可用。当他们回到视野中时,通过改变焦点或位置等,系统将通知该区域重新绘制自己。但是,在使用桌面合成时,永远不需要重新绘制,因为窗口的实际内容会在其他位置缓冲。这就是窗口预览在任务栏和Flip-3d中工作的原因。副作用是,在被遮挡后再次可见的期望获得绘制消息的代码将失败。 ButtonBase代码一旦返回视图就会收到一条paint消息,这将再次启动动画。因此,这种优化成了一个错误。
应该在Microsoft Connect中报告此问题,但不太可能解决。