基本上我是从头开始制作动画UI的。UI上的所有内容都派生自ScreenThing基类,该基类可以存储用于绘制该对象的位图及其位置。当我想绘制UI时,我会创建一个大小合适的新空白位图,从该位图创建一个Graphics对象,然后将该Graphics对象传递给所有ScreenThingsDraw()方法来绘制它们自己。完成后,我使用PictureBox控件将位图打印到屏幕上。
这一切都很好,但太慢了。我希望这种情况每秒至少发生30次,这样动画才会流畅,但这一切都需要33毫秒以上的时间。我已经看到这种缓慢的原因是位图内存的锁定和解锁。我尝试了一些我在网上找到的代码,这些代码可以解锁位图,并创建一个新的GetPixel和SetPixel函数,并尝试像下面这样逐像素组合图像,但这需要更长的时间。(下面的代码只是一个测试,它没有把图像放在正确的位置)
for (int i = 0; i < images.Count; i++)
{
FastBitmap foreground = new FastBitmap(images[i]);
foreground.LockImage();
for (int x = 0; x < images[0].Width; x++)
{
for (int y = 0; y < images[0].Height; y++)
{
output.SetPixel(x, y, foreground.GetPixel(x, y));
}
}
foreground.UnlockImage();
}
那么,最好的方法是什么呢?有可能像这样使用C#实时绘制一个相当大的图像(比如1024x768)吗?如果所有其他方法都失败了,我想我可以找到一种方法,只画出已经改变的部分,但如果可以用蛮力重新绘制所有内容,我很乐意避免这样做。非常感谢!
使用位图绘制实时动画的效率非常低。Insted,创建一个CustomControl,并覆盖其OnPaint方法,如下所示:
protected override void OnPaint(PaintEventArgs pe)
{
}
在那里你可以使用pe.Graphics来绘制任何你想要的图形,而不需要复制到屏幕上。我用过它,如果你画的程序相当快,那会很顺利。
此外,请记住在控制构造函数中调用SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
以获得双缓冲
逐像素方法是最糟糕的方法。相反,您应该评测应用程序。这很简单:在全工作负载(100%cpu)下运行它,并暂停调试器10次。看看它停得最多的地方,那就是你必须优化的热点。