Winforms中自定义控件绘制的最佳实践?

时间:2009-11-11 21:27:38

标签: c# .net winforms gdi+

通常当我覆盖OnPaint方法时,我会在其中创建笔和画笔等,然后处理它们。

我还在某处阅读,而不是重新创建这些笔和画笔等,以创建它们一次作为静态成员,然后在窗体关闭时将它们处理一次,等等。

这是一种更好的做法吗?

有更好的方法吗?

我可以假设,由于OnPaint被称为1000s(?)次,与仅创建一次相比,这会为GC创造大量工作。

5 个答案:

答案 0 :(得分:8)

如果刷子和笔没有变化,创建它们并重复使用它们肯定会更好。但请注意,如果您的控件可能在多个线程上使用(这是非常不可能的),您应该使它们ThreadStatic(并在每个线程首次使用时初始化)或将它们作为实例成员(并将它们置于你的控件的Dispose覆盖);否则,您将获得无法生成的GDI +错误,因为GDI +对象不能同时在多个线程上使用。图像也是如此。

如果它们确实发生了变化(例如,如果使用依赖于控件大小的渐变画笔),您可能仍希望将它们存储在实例字段中,并在控件的大小(或其他)更改时重新创建它们。 / p>

顺便说一句,请注意,如果使用普通颜色,则可以使用静态BrushesPens类,其中包含静态画笔和笔,用于.Net的所有内置颜色,系统颜色以及SystemBrushesSystemPens

答案 1 :(得分:2)

上个月我读了interesting article,建议你把所有的绘画都放到一个单独的BufferedGraphics对象上,然后让on_paint方法直接复制到你控件的图形对象。

这样,on-paint就会更快,只有在发生重大变化(即行移动或文本更改)时才会更新BufferedGraphics。

答案 2 :(得分:1)

我要做的是将画笔和笔作为自定义控件的成员,然后在处理控件时处理它们。这样,每次调用OnPaint时都会重复使用相同的笔刷/笔。

我不会声明它们static,因为你无法知道什么时候可以丢弃你的物体。但正如SLaks所提到的,如果同时在内存中存在许多控件实例,那么将画笔和笔创建为静态是一个好主意,这样在应用程序的生命周期中只创建每个对象的一个​​实例

答案 3 :(得分:1)

我真的要看你画的是什么。如果您只绘制一些仅在用户交互的情况下重新绘制的内容,您可以放弃性能上的担忧,并在需要时即时创建所有图形对象。

确保Dispose()图形中需要的所有内容。钢笔,画笔,区域,字体。这些都是GDI对象,并通过GDI句柄绑定到系统中。

如果您需要以某种方式设置动画的图形或在没有用户单击的情况下及时更改图形,请在前面准备好所有图形对象并尽可能多地重复使用它们。这里可以应用的规则是,在绘制动画的每一帧时,最好浪费内存,然后是毫秒。

最后,至少对于这篇文章 - 不要忘记使用双缓冲,自动在.net控制系统或滚动你自己的后位图样式。

玩得开心GDI-ing:)

答案 4 :(得分:0)

最佳做法是使用系统笔和画笔,因为这些是针对最小资源消耗进行优化的。