使用 C#/Windows 窗体的简单动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/188349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple animation using C#/Windows Forms
提问by Clinton Pierce
I need to knock out a quick animation in C#/Windows Forms for a Halloween display. Just some 2D shapes moving about on a solid background. Since this is just a quick one-off project I reallydon't want to install and learn an entire new set of tools for this. (DirectX dev kits, Silverlight, Flash, etc..) I also have to install this on multiple computers so anything beyond the basic .Net framework (2.0) would be a pain in the arse.
我需要在 C#/Windows 窗体中制作一个用于万圣节展示的快速动画。只是一些在纯色背景上移动的 2D 形状。由于这只是一个快速的一次性项目,我真的不想为此安装和学习一整套新工具。(DirectX 开发工具包、Silverlight、Flash 等。)我还必须在多台计算机上安装它,因此除了基本的 .Net 框架 (2.0) 之外的任何东西都会很麻烦。
For tools I've got VS2k8, 25 years of development experience, a wheelbarrow, holocaust cloak, and about 2 days to knock this out. I haven't done animation since using assembler on my Atari 130XE (hooray for page flipping and player/missile graphics!)
对于工具,我拥有 VS2k8、25 年的开发经验、手推车、大屠杀斗篷,以及大约 2 天的时间来解决这个问题。自从在我的 Atari 130XE 上使用汇编程序后,我就没有做过动画(用于翻页和播放器/导弹图形!)
Advice? Here's some of the things I'd like to know:
建议?以下是我想知道的一些事情:
- I can draw on any empty widget (like a panel) by fiddling with it's OnPaint handler, right? That's how I'd draw a custom widget. Is there a better technique than this?
- Is there a page-flipping technique for this kind of thing in Windows Forms? I'm not looking for a high frame rate, just as little flicker/drawing as necessary.
- 我可以通过摆弄它的 OnPaint 处理程序来绘制任何空的小部件(如面板),对吗?这就是我绘制自定义小部件的方式。还有比这更好的技术吗?
- Windows Forms 中是否有针对此类事情的翻页技术?我不是在寻找高帧率,只是需要尽可能少的闪烁/绘图。
Thanks.
谢谢。
Post Mortem Edit ... "a couple of coding days later"
事后编辑......“几天后编码”
Well, the project is done. The links below came in handy although a couple of them were 404. (I wish SO would allow more than one reply to be marked "correct"). The biggest problem I had to overcome was flickering, and a persistent bug when I tried to draw on the form directly.
好了,项目完成了。下面的链接派上了用场,尽管其中有几个是 404。(我希望 SO 允许将多个回复标记为“正确”)。我必须克服的最大问题是闪烁,以及当我尝试直接在表单上绘制时一个持续存在的错误。
- Using the OnPaint event for the Form: bad idea. I never got that to work; lots of mysterious errors (stack overflows, or ArgumentNullExceptions). I wound up using a panel sized to fill the form and that worked fine.
- Using the OnPaint method is slow anyway. Somewhere online I read that building the PaintEventArgs was slow, and they weren't kidding. Lots of flickering went away when I abandoned this. Skip the OnPaint/Invalidate() and just paint it yourself.
Setting all of the "double buffering" options on the form still left some flicker that had to be fixed. (And I found conflicting docs that said "set them on the control" and "set them on the form". Well controls don't have a .SetStyle() method.) I haven't tested without them, so they might be doing something (
this
is the form):this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- 为 Form 使用 OnPaint 事件:坏主意。我从来没有让它起作用;许多神秘的错误(堆栈溢出或 ArgumentNullExceptions)。我最终使用了一个面板大小来填充表格,效果很好。
- 无论如何,使用 OnPaint 方法很慢。我在网上的某个地方读到构建 PaintEventArgs 很慢,他们不是在开玩笑。当我放弃这个时,很多闪烁都消失了。跳过 OnPaint/Invalidate() 并自己绘制它。
在表单上设置所有“双缓冲”选项仍然会留下一些必须修复的闪烁。(我发现有冲突的文档说“在控件上设置它们”和“在表单上设置它们”。控件没有 .SetStyle() 方法。)没有它们我没有测试过,所以它们可能是做某事(
this
是形式):this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
So the workhorse of the code wound up looking like (pf
is the panel control):
所以代码的主力看起来像(pf
是面板控件):
void PaintPlayField()
{
Bitmap bufl = new Bitmap(pf.Width, pf.Height);
using (Graphics g = Graphics.FromImage(bufl))
{
g.FillRectangle(Brushes.Black, new Rectangle(0, 0, pf.Width, pf.Height));
DrawItems(g);
DrawMoreItems(g);
pf.CreateGraphics().DrawImageUnscaled(bufl, 0, 0);
}
}
And I just called PaintPlayField from the inside of my Timer loop. No flicker at all.
我只是从我的 Timer 循环内部调用 PaintPlayField 。完全没有闪烁。
采纳答案by Nick
Set off a timer at your desired frame rate. At each timer firing twiddle the internal representation of the shapes on the screen (your model) per the animation motion you want to achieve, then call Invalidate(true)
. Inside the OnPaint just draw the model on the screen.
以您想要的帧速率启动计时器。在每个计时器触发时,根据您想要实现的动画运动在屏幕(您的模型)上旋转形状的内部表示,然后调用Invalidate(true)
. 在 OnPaint 中,只需在屏幕上绘制模型即可。
Oh yeah, and you probably want to turn Double Buffering on (this is like automatic page flipping).
哦,是的,您可能想打开双缓冲(这就像自动翻页)。
回答by StubbornMule
Both of these give good examples of animation. The code is fairly straightforward. i used these when I needed to do a quick animation for my son.
这两个都提供了很好的动画示例。代码相当简单。当我需要为我儿子做一个快速动画时,我使用了这些。