C#PictureBox控制闪烁/性能问题

本文关键字:性能 问题 闪烁 控制 C#PictureBox | 更新日期: 2023-09-27 18:20:52

我目前在Windows窗体应用程序中工作,正在为游戏制作一个地图编辑器。我实现这一点的方式是通过具有一个中央TabControl,其中每个TabPage都包含一个自定义PictureBox控件,并且所有其他UI控件都围绕着这个中央TabControlPictureBox使用其"绘制"事件绘制放置在地图上的所有内容,因此为单个PictureBox绘制多个大小、旋转和比例等的图像。到目前为止一切进展顺利。TabPage主要用作PictureBox的视图窗口,其大小为(1280x720)。

问题在于地图制作的比例。屏幕上的平均(也是最大)地图大小约为19200x10800px,可以在任何一点由数百个项目组成。当只绘制尺寸19200x10800px的背景图像时,PictureBox在重新绘制时开始闪烁,并使程序不可用。由于地图太大了,你可以在它们周围平移,这就是闪烁真正显示的地方。此外,如果可能的话,我不想使用19200x10800px图像源,因为文件大小和缩放后的图像质量根本不是问题。

我已经读了很多关于为什么会这样的书,感觉我已经尝试了所有的东西,直到现在。到目前为止,我尝试过:

  • 背景图像只有1920x1080,并将其放大10倍
  • 从一张1920x1080的图像开始,用程序调整其大小并绘制此图像
  • 将背景分割成多个片段(我尝试了许多不同的量),并只绘制视图窗口可以看到的片段(尝试了小(1080p)和大(10800p)图像)
  • 使用图形剪辑,以便只绘制屏幕上的内容
  • 在picturebox和picturebox所在的窗体上使用双重缓冲
  • 将初始化时的图像转换为具有更快格式的"优化位图",然后绘制位图

我可能尝试过其他一些小的优化,但花了很长时间才忘记了其余的。从我所读到的内容来看,很可能是由于某种性能原因或picturebox的限制,控件重新绘制太慢,但由于缺乏表单应用程序控件的经验,我无法判断到底发生了什么。

目前,为了在Paint事件中绘制背景,我有以下任一选项:

g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width * levelScale), (int)(image.Size.Height * levelScale)));

g.ScaleTransform(levelScale, levelScale);
g.DrawImage(image, new Rectangle(0, 0, (int)(image.Size.Width), (int)(image.Size.Height)));

其中g是Graphics对象。

我是否达到了Win表单应用程序功能的极限,或者我可能缺少什么?

感谢所有帮助,

提前谢谢。

C#PictureBox控制闪烁/性能问题

只是为了形式,我想我会回答自己的问题,以防其他人想知道结果。

基于压倒性的共识,即winforms并不是用来做我试图用它做的事情的,我决定我必须转到其他平台。建议我使用WPF、DirectX和OpenGL,但经过广泛的搜索,我发现了我认为是最佳解决方案。

为了利用DirectX硬件加速的强大功能,MS使您可以将XNA图形设备嵌入到winforms应用程序中。从本质上讲,您可以创建以普通winform样式运行的自定义控件,这些控件可以访问更高级别的图形控件。通过这种方式(加上一些额外的工作),我用一个处理所有绘图的自定义图形控件替换了我使用的picturebox。这样做效果很好,从好的方面来说,我的发展时间没有受到太大的打击。

对于那些寻找更多信息的人,请参阅这个问题,它有进一步的链接,应该会有所帮助。再次感谢所有提出建议的人!

这是底部URL中的一个引用答案。下面的链接中有一些代码示例。希望这是有帮助的;不确定你是否尝试过这个,也许它会帮助你从现有的picturebox控件中获得更多的果汁。正如在其他答案中所解释的,听起来在不久的将来,无论(DirectX/OpenGL或WPF)如何,你都将被迫使用更强大的解决方案

**部分引用自http://social.msdn.microsoft.com/Forums/en-US/68ecd1f6-2eeb-45ce-a881-24c62145ab0e/c-picturebox-problems

"我想真正的问题是重新绘制图像需要太长时间。GDI+速度很慢,它不使用任何视频硬件加速。要加快速度,请确保避免重新缩放绘图,并使用Format32PArgb格式。它比任何其他格式都快10倍。先将图像加载到具有正确格式的位图中。"

如果您有很多项(可能是作为控件实现的),请忘记Windows窗体的标准事件机制。前段时间,我写了一个逻辑门编辑器/模拟器,它支持编辑器中成千上万的门,速度非常快。在那里,我使用了画布,并将大门绘制为自定义的"图像",而不是将其作为控件。您必须编写一个自定义GetUnderlyingGate函数,该函数从坐标阵列解析当前门/瓦片(您的编辑器是瓦片映射编辑器吗?)。此外,还有一些可视区域优化。

也许,当我回家的时候,我会上传一些源代码并通知你。