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

时间:2013-07-03 07:38:01

标签: c# winforms scaling picturebox

我目前正在 Windows窗体应用中工作,我正在制作一款基本上是游戏的地图编辑器。我这样做的方法是设置一个中心TabControl,其中每个TabPage包含一个自定义PictureBox控件,所有其他UI控件都围绕此中心TabControlPictureBox使用其Paint事件绘制放置在地图上的所有内容,因此将多个大小,旋转和比例等的图像绘制到单个PictureBox。到目前为止,这一切都进展顺利。 TabPage基本上用作PictureBox的视图窗口,大小(1280x720)。

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

我已经大量阅读了为什么会这样,并且觉得我已经尝试过所有事情,直到这一点。到目前为止,我尝试过:

  • 背景图片仅为1920x1080,并将其缩放10倍
  • 从1920x1080图像开始,以编程方式调整大小并绘制此图像
  • 将背景分成多个片段(我尝试了很多不同的数量)并仅绘制了视图窗口可以看到的片段(对于小型(1080p)和大型(108000p)图像都尝试了这种情况)
  • 使用图形剪辑,以便只绘制屏幕上的内容
  • 在图片框和图片框所在的表格上使用双缓冲
  • 将初始化时的图像转换为“优化位图”,格式化更快,然后绘制位图

我可能尝试了其他一些事情以及一些小的优化,但它花了很长时间我忘记了其余的事情。从我所读到的最有可能的事情来看,控制重绘速度太慢,出于某种性能原因或者对于图片框的限制,但是由于缺乏表单应用程序控件的经验,我无法判断的是什么。 / p>

目前要在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表单应用程序功能的限制,还是有些东西可能会丢失?

任何和所有帮助表示赞赏,

提前致谢。

3 个答案:

答案 0 :(得分:4)

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

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

为了利用DirectX硬件加速的强大功能,MS已经将XNA图形设备嵌入到winforms应用程序中。基本上,您可以创建以正常winform样式运行的自定义控件,这些控件可以访问更高级别的图形控件。以这种方式(有一些额外的工作)我已经用我自己使用的图片框替换了处理所有绘图的自定义图形控件。这非常有效,而且从好的方面来说,我的开发时间不会太大。

对于那些寻求更多信息的人,请参阅this问题,该问题还有其他可能有用的链接。再次感谢所有提出建议的人!

答案 1 :(得分:1)

这是来自底部网址的引用答案。底部的链接有代码示例。希望这有用;不确定你是否尝试过这个,也许它可以帮助你从现有的图片盒控件中获得更多的果汁。正如在其他答案中解释的那样,听起来你将在不久的将来被迫使用更强大的解决方案(DirectX / OpenGL或WPF)

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

的部分引用

“我猜真正的问题是重绘图像需要很长时间.GDI +非常慢,它不使用任何视频硬件加速。为了加快速度,请务必避免重新缩放图形和使用Format32PArgb格式。它比任何其他格式快10倍。将图像加载到具有正确格式的位图中。“

答案 2 :(得分:0)

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

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