Direct2D / GDI+ Windows 窗体绘图缓慢 - 可以做什么?
我经常使用 Visual Studio 2008、.NET C# 2.0-3.5 和 Windows 窗体,并且像我之前的许多人一样,我注意到 GDI+ 绘制控件的速度非常慢。请注意,我不太处理图像(JPG、GIF 等)。图像仅在某些地方作为图标。这实际上是绘制速度很慢的控件/表单/等。
问题是,您可以看到正在绘制的控件,但绘制一组看似简单的控件可能需要几秒钟的时间。即,它是滞后的并且可怕的。
我已经进行了测试,我只是在表单上放置了一些标签(40-50),按 F5 运行并必须等待它们被绘制。再说一次,延迟,这不是一个很好的体验。
因此,WPF 可能会解决这个问题,但我/我们还没有准备好转向 WPF。因此,我正在寻找解决方法或修复方法,并且在阅读其他一些库时偶然发现了 Direct2D。
我很困惑,因此有以下问题:
首先,我想要的是一种相当简洁的方法,用更快的硬件加速方法替换 GDI+。 是否可以在不转到 WPF 且无需重写所有 Windows 窗体代码的情况下做到这一点?
每当我在 Direct2D 上阅读任何内容时,我都会看到很长的通常很糟糕的 C++ 代码块,告诉我如何手动编写代码来进行绘图。我不想这样。
在网上阅读时,我偶然发现了 SlimDX,但我不知道如何使用它(我承认,在撰写本文时我还没有进行太多尝试)。假设我已经有一个 GUI 应用程序(Windows 窗体、标准 C# 代码) - 我可以以某种方式使用 SlimDX(或类似的东西)来“替换”GDI+ 而无需太多重写吗?
我的问题是我找不到任何示例或类似的例子来告诉我是否可以在我已经创建的 Windows 窗体软件中使用 SlimDX、Direct2D 或其他类似的东西,以及如果可以的话 - 如何去做。
编辑1
我在我的真实应用程序中进行了一些测试,并将其中一个缓慢的事情与此隔离:
当我将文本添加到用户控件中的某些标签时,控件会调整自身大小以适应文本。例如,包含的 GroupControl 会稍微适应刚刚添加到标签的 .Text 属性中的文本的大小。
大约有 10 个 Label 控件。第一次更新标签并因此更改大小时,整个过程大约需要 500 毫秒。第二次更新标签且大小没有变化时,大约需要 0 毫秒。
编辑2
发现速度减慢之一。然后将字符串添加到文本属性,如果要添加的文本的字符串长度与更新之前的文本不同,则速度会很慢。
我正在使用 DevExpress 库,并且 LabelControls 可以设置为 AutoSizeMode。如果我将其设置为“无”,那么当添加长度与先前文本不同的文本时,滞后就会消失。我想这个问题对于普通的标签控件来说是一样的,因为它也有一个 AutoSize = true/false 设置。
然而,这是一个“解决方法”,但仍然证明了我的观点 - 调整大小时真的很慢。
I'm working a lot with Visual Studio 2008, .NET C# 2.0-3.5 and Windows Forms and I have noticed, like many before me, that GDI+ is extremely slow in drawing Controls. Note that I do not deal with images (JPG, GIF etc) very much. Images are only as icons in certain places. This is actually Controls/Forms/etc that are slow to draw.
The issue is that you can see Controls being drawn and it can take several seconds for a seemingly easy set of Controls to be drawn. Ie, it's lagging and horrible.
I have made tests where I just put a number of Labels (40-50) on a form, hitting F5 to run and have to wait for them to be drawn. Again, lag and not a very nice experience.
So, then there is WPF that might address this problem, but I/we are not ready to move to WPF. So I'm looking around for workarounds or fixes and I stumbled upon Direct2D, and when reading on that some other libraries.
I'm puzzled and thus have these questions:
Firstly, what I want is a fairly neat and simple way to just replace GDI+ with something faster and hardware accelerated approach. Is it possible to do that without going over to WPF and without having to rewrite all my Windows Forms code?
Whenever I read anything on Direct2D I see long blocks of usually horrible C++ code, telling me on how to manually write code to for drawing. I do not want that.
While reading on the net, I stumbled upon SlimDX, but I cannot figure out how to use it (and I admit, I haven't tried very much as of writing). Let's say I already have a GUI-application (Windows Forms, standard C# code) - can I somehow use SlimDX (or something like it) to just "replace" GDI+ without too much rewriting?
My problem is I cannot find any examples or such telling me if it is possible to use SlimDX, Direct2D or other similar things in my already-created Windows Forms software, and if it is possible - how to do it.
Edit 1
I have made some tests in my real app, and isolated one of the slow things to this:
When I add text to some Labels in a UserControl, the Controls resize themselves to fit the text. For example, the containing GroupControl adapts a bit to the size of the text that was just added to the .Text-property of the Labels.
There are about 10 Label controls. The first time the labels are updated, and thus sizes are changed, the whole process takes about 500 ms. The second time the labels are updated, and no size changes, it takes about 0 ms.
Edit 2
Found one of the slow-downs. Then adding a String to the Text-property it is slow if the text that is being added differs in string length from the text that was there before the update.
I'm using DevExpress libraries, and the LabelControls can be set to AutoSizeMode. If I set that to "None" then the lag will go away when adding text that differs in length from the previous text. I guess this problem will be the same for the normal Label-control as it also has a AutoSize = true/false setting.
However, it's a "workaround" but still proves my point - it's really slow when resizing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
上面的许多海报都有很好的观点。我自己在 GDI+ 中创建了一个 3D CAD 应用程序,并且发现如果正确实现,它的速度足够快。然而,使用控件立即让我觉得这是一种非常尴尬的做事方式。控件是一个相当大的对象,在这种情况下有很多理由要创建自己的对象。
我建议您查看 保留模式绘制系统。它很容易实施,并且在大多数情况下可以满足您的情况。您必须自己创建绘图逻辑,但这很有趣并且会给您带来更大的灵活性:)
Many of the posters above come with good points. I've created a 3D CAD application in GDI+ myself, and found it plenty fast enough if it's implemented correctly. Using Controls, however, immediately strikes me as a very awkward way to do things. A Control is a fairly big object and there are numerous reasons to make your own in this case.
I'd advise you to look into a retained mode drawing system. It's easy to implement and would cover your situation in most cases. You'd have to create the drawing logic yourself, but that's just fun and would give you more flexibility :)
关于你的第一个问题,我不得不使用 GDI 来做一些图像处理工作,这在 GDI+ 下需要很长时间。这是 4-5 年前的事,使用托管 C# 来处理 GDI 是一件痛苦的事 - 不知道现在发生了多大变化。有许多又好又快的函数,例如 BitBlt,它们的绘图速度非常快,但您需要非常小心地释放资源(句柄)和内存。我还有另一个问题,即将结果保存为 JPEG,但它在 GDI 中不存在,因此我必须使用 CxImage 读取 HBitmap,然后保存它。
总而言之,GDI 非常快速且强大。如果 DirectX 中有更好的抽象,那么您最好使用它们。
On your first question, I had to use GDI to do some image processing stuff which was taking ages under GDI+. This was 4-5 years ago and working with GDI using managed C# was a pain - not sure how much it has changed now. There are many good and fast functions such as BitBlt which are very fast in drawing but you need to be very careful with releasing resources (handles) and memory. I also had another issue and that was saving the result as JPEG and it is non-existent in GDI so I had to use CxImage to read the HBitmap and then save it.
All in all, GDI is very fast and robust. If there better abstractions in DirectX, probably you are better off using them.
我正在研究一些相同的问题。我正在编写一个应用程序,需要能够非常有效地渲染 2d 图形,因为某些用户可能会同时打开 10 - 50 个窗口。需要考虑的一件事是,这里没有其他人谈到,direct2d 只能在具有 Service Pack 2 及更高版本的 Vista 计算机上使用。另外,根据此链接:
http://www.tomshardware.com/news/msft-windows-xp-windows-7-market-share-win7,13876.html
截至 2011 年 11 月,38.5% 的 Windows 用户仍在使用 XP因此,如果您担心将应用程序销售给仍然运行 XP 的大量用户(或者您的市场基础是主要使用 XP 的第三世界国家),那么您应该选择:
适用于较新操作系统的 Direct2d。和 GDI+ 用于 XP 系统。
XNA - 与 XP 兼容,也可以与较新的操作系统一起使用。请参阅此链接:http://msdn.microsoft.com/en-us/library /bb203925.aspx
SlimDX - 在第一个答案中提到。支持 XP 以及更新的操作系统。看:
http://slimdx.org/ 和 http://slimdx.org/features.php
如果您关心 Windows、Linux、Max 等之间的兼容性,请使用 OpenTK。
您还应该知道 GDI+ 存在一个错误,导致其在最初发布时性能非常差。请参阅以下链接,了解为什么一些开发人员声称 Microsoft 破坏了使用 GDI+ 的应用程序的 Windows7 图形用户界面:
http://www .windows7taskforce.com/view/3607
或使用以下字符串从您最喜欢的搜索引擎进行网络搜索:“gdi+ bug Slow on windows 7”。
I'm looking at some of the same issues. I am writing an application that needs to be able to render 2d graphics very efficiently since some users could have 10 - 50 windows open simultaneously. One thing to consider that no one else talked about here is the fact that direct2d can only be used on computers with Vista with service pack 2 and up. Also, according to this link:
http://www.tomshardware.com/news/msft-windows-xp-windows-7-market-share-win7,13876.html
38.5% of all Windows users were still using XP as of Nov, 2011. So, if selling the app to a significant amount of users still running XP is a concern (or your marketbase is to 3rd world countries that are mainly using XP), then you should either go with:
Direct2d for newer operating systems and GDI+ for XP systems.
XNA - which is compatible with XP and can also be used with newer operating systems. See this link: http://msdn.microsoft.com/en-us/library/bb203925.aspx
SlimDX - mentioned in the first answer. Supports XP as well as newer operating systems. See:
http://slimdx.org/ and http://slimdx.org/features.php
OpenTK if you care about compatibility between Windows, Linux, Max, etc.
You should also be aware that there was a bug with GDI+ that caused it to suffer very poor performance when it was initially released. See the following link why some developers claim that Microsoft broke the gui for Windows7 for apps using GDI+:
http://www.windows7taskforce.com/view/3607
or do a web search from your favorite search engine with this string: "gdi+ bug slow on windows 7".
您可以尝试托管 directx,但他们不再支持它(转向 XNA)。老实说,除非你有一台糟糕的电脑或大量的控件,否则我不知道为什么它会如此严重地滞后。如果您在主线程上执行一些 CPU 密集型操作,请将其移至单独的线程。这是我能想到的导致这种滞后的唯一其他原因。
You could try managed directx, but they no longer support it (moved on to XNA). Honestly, unless you've got a shitty computer or a ton of controls, I don't know why it'd be lagging so bad. If you're doing some cpu intensive stuff on your main thread, move it to a separate thread. That's the only other reason I can think of that'd cause that kind of lag.
我们在 C# 应用程序中使用 SlimDX...但我们实际上是在做 3D。我们编写了自己的 2D 库,以便能够进行简单的 2D 绘图。 SlimDX 只是 DirectX 的轻量级包装。因此,您将了解 DirectX 的所有优点和缺点。就像这样,如果视频卡不存在,那么模拟视频卡就是你的问题。
如果你想要一些东西来绘制离屏位图,我会选择 WPF,因为它与 C# 很好地集成,几乎可以在任何地方工作,并且在有可用硬件时可以加速。您可以将输出复制到位图并在常规 GDI/Winforms 中使用它。但如果你做相当复杂的事情(很多过滤器、混合纹理等......),它只会比 GDI+ 更快。
编辑:
为了回应评论,我构建了一个小示例表单。第一次切换时需要等待一秒钟,但之后就会有响应。比我预期的慢,但无论如何可用。希望 Ted 评论一下这是否与他在应用程序中看到的性能有关。
We use SlimDX in our C# app.... But we're actually doing 3D. We wrote our own 2D lib to be able to do simple 2D drawing. SlimDX is just a lightweight wrapper around DirectX. So you'll get all of the pro's and cons of DirectX. Like that it's your problem to emulate the videocard if its not present.
If you want something for drawing to offscreen bitmaps, I'd go for WPF, as it is well integrated with C#, works mostly everywhere, and accellerated when there's hardware available. You can copy the output to a bitmap and use that in regular GDI/Winforms. But it will only be faster than GDI+ if you do fairly complex stuff (lots of filters, mixing textures etc...).
Edit:
In response to the comments, I built a little sample form. There is a seconds long wait when switching the first time, but after that it's responsive. Slower than I'd expect, but by all means usable. Would like Ted to comment if this is about the performance he is seeing in his app.