.net 2010 从自定义控件库中调用 DoEvents(是的,我想)
我有一个自定义控件的库。现在有一个看起来像面板的控件,当它打开时,我想为其垂直生长设置动画,如下所示:
For h As Single = 0 To finalHeight Step 0.5
Me.Height = CInt(h)
' HERE I WANT TO CALL DoEvents'
Next
Me.Height = finalHeight
如果我不在循环中调用 DoEvents,则不会显示动画,我只能获得最终高度,而无需沿途视觉反馈。
我可以从我的主 WinForm 项目中调用 DoEvents,但不能在库中调用。
我怎样才能做到这一点,而不被淹没在深水里?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
抱歉,在这里完全不可能安全地使用 DoEvents。当用户在动画运行时关闭表单时,不会发生任何好事。它将导致程序因 ObjectDispose 异常而崩溃。要确保 DoEvents 安全,需要将表单的 Enabled 属性设置为 false,以便用户不会意外导致此类事故。控件无法合理地将表单的 Enabled 属性设置为 false,尤其是对于动画。
解决方法很简单,只需使用间隔为 15 毫秒的计时器即可。速度足够快,可以让动画看起来很流畅。您将在我的答案中找到执行此操作的示例代码 此帖子。
Sorry, but it is completely impossible to make using DoEvents safe here. Nothing good is going to happen when the user closes the form while your animation is going. It will crash the program with an ObjectDisposed exception. Making DoEvents safe requires setting the form's Enabled property to false so that the user cannot accidentally cause mishaps like this. A control can not reasonable set the form's Enabled property to false, especially not for an animation.
The workaround is simple enough, just use a Timer with an Interval of 15 msec. Plenty fast enough to make the animation look smooth. You'll find sample code that does this in my answer in this thread.
也许您只是缺少对 System.Windows.Forms 的引用(或导入)?
DoEvents
是Application
的静态方法,因此您也应该能够从库中调用它。(您似乎已经知道使用
DoEvents
是一件危险的事情,所以我将在这里跳过通常的讲座。)Maybe you are just missing a reference to (or import of)
System.Windows.Forms
?DoEvents
is a static method ofApplication
, so you should be able to call it from a library as well.(You already seem to know that using
DoEvents
is a dangerous thing, so I'll skip the usual lecture here.)是的,您应该能够
在代码库中调用 From 。看来您明白 DoEvents 是一个坏主意,所以我不确定您为什么要调用它。我猜测您已将其放入 OnVisibleChanged 或 OnPaint 之类的覆盖中 - 如果是这种情况,您很可能不会得到您想要的结果,因为在这些操作期间控件刷新将被暂停。
您可能想要做的是创建一个单次滴答计时器,并在滴答时增加控件的高度 - 然后在达到最终高度时禁用计时器,或者如果没有达到则安排另一个滴答。或者,创建一个计时器并在每次滴答时将上面的循环放入其中。确保您了解
InvokeRequired
和跨线程调用,具体取决于您使用的计时器类型。Yes, you should be able to call
From within your code library. It seems that you understand that DoEvents is a Bad Idea, so I'm not sure why you're calling it. I'm guessing that you have this put inside an override like OnVisibleChanged, or OnPaint - if this is the case you will most likely not get the results you are after, as control refreshing will be suspended during these operations.
What you probably want to do is create a single-tick timer, and on tick increase the height of the control -then disable the timer when finalheight is reached, or schedule another tick if not. Or, create a timer and put your above loop in it on each tick. Make sure you're aware of
InvokeRequired
and cross-thread calls depending on what type of timer you use.无法重现。
刚刚在程序集中使用简单的设置 UserControl 进行了测试。
当 UC 在循环中调用 DoEvents() 时,MainForm 上的计时器会持续计时。
所以:再看看你的问题,它不是你想象的地方。
Failure to reproduce.
Just tested with a simple setup, UserControl in an assembly.
A timer on the MainForm keeps ticking when the UC calls DoEvents() in a loop.
So: Look again for your problem, it isn't where you think it is.
在原始 for 循环中,将
Me.Refresh
放置在您要调用 doevents 的位置。In your original for loop, place
Me.Refresh
where you wanted to call the doevents.这就是我发现的:计时器即使间隔很快,它也非常慢。我不知道为什么,但计时器的动画非常跳跃。简化的代码:
没有计时器,我使用循环:
它现在可以工作,但问题是动画速度太多取决于执行循环的机器。由于这个原因,我想使用计时器,但正如我所说,它太慢了。
有什么提示吗?
This is what I've found: the timer, even at fast intervals, it is really slow. I don't know why but the animation is very jumpy with the timer. Simplified code:
Without the timer I use a loop:
It works now, but the problem is that the animation speed too much depends on the machine where the loop is executed. For this reason I'd like to use a Timer, but as I said it's too slow.
Any hints?