简体   繁体   English

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

[英]Best practice for custom control painting in Winforms?

Normally when I override the OnPaint method, I create pens and brushes, etc inside it and then dispose them. 通常当我重写OnPaint方法时,我会在其中创建笔和画笔等,然后处理它们。

I also read somewhere that instead of recreating these pens and brushes, etc to create them once as static members, and then dispose them once when the form is closed, etc. 我也读过一些地方,而不是重新创建这些笔和画笔等,以创建它们一次作为静态成员,然后在窗体关闭时将它们处理一次,等等。

Is this a better practice? 这是一种更好的做法吗?

Is there a better way for this? 有更好的方法吗?

I can assume that since OnPaint is called 1000s (?) of times, that would create a lot of work for the GC compared to creating them only once. 我可以假设,由于OnPaint被称为1000s(?)次,与仅创建一次相比,这将为GC创建大量工作。

If the brushes and pens don't change, it's certainly better to create them once and reuse them. 如果刷子和笔没有变化,那么创建它们并重复使用它们肯定会更好。 Note, however, that if your control might be used on multiple threads (which is very unlikely), you should either make them ThreadStatic (and initialize on first use per thread) or make them instance members (and dispose them in your control's Dispose override); 但请注意,如果您的控件可能在多个线程上使用(这是非常不可能的),您应该将它们设置为ThreadStatic (并在每个线程首次使用时初始化)或将它们设置为实例成员(并将它们放置在控件的Dispose覆盖中) ); otherwise, you'll get unreproducable GDI+ errors, as GDI+ objects cannot be used on multiple threads at once. 否则,您将获得无法生成的GDI +错误,因为GDI +对象不能同时在多个线程上使用。 The same is true for images. 图像也是如此。

If the they do change (for example, if you use gradient brushes which depend on the control's size), you might still want to store them in instance fields, and recreate them when the control's size (or whatever) changes. 如果它们确实发生了变化(例如,如果使用依赖于控件大小的渐变画笔),您可能仍希望将它们存储在实例字段中,并在控件的大小(或其他)更改时重新创建它们。

Note, by the way, that if you use normal colors, you can use the static Brushes and Pens classes, which contain static brushes and pens for all of .Net's built-in colors, and SystemBrushes and SystemPens for system colors. 请注意,顺便说一下,如果你用正常的颜色,你可以使用静态BrushesPens类,其中包含了所有的.NET的静态刷子和笔内置的色彩, SystemBrushesSystemPens系统颜色。

I read an interesting article last month which suggested doing all of your painting onto a separate BufferedGraphics object, and have the on_paint method do a straight copy from that to your control's graphics object. 我上个月读了一篇有趣的文章 ,建议你把所有的绘画都放到一个单独的BufferedGraphics对象上,然后让on_paint方法直接复制到你的控件的图形对象。

That way, the on-paint is faster, and you only update your BufferedGraphics when something significant changes (ie a line moves or text changes). 这样,on-paint就会更快,只有在发生重大变化(即行移动或文本更改)时才会更新BufferedGraphics。

What I'd do is have the brushes and pens as members of the custom control, then dispose them when disposing of the control. 我要做的是将画笔和笔作为自定义控件的成员,然后在处理控件时处理它们。 This way you reuse the same brush/pen every time OnPaint is called. 这样,每次调用OnPaint时都会重复使用相同的笔刷/笔。

I wouldn't declare them static though, because you wouldn't be able to know when you can dispose of your objects. 我不会声明它们是static ,因为你无法知道何时可以处理你的物体。 But as SLaks mentioned, if there are many instances of the control in memory at the same time, it can be a good idea to create brushes and pens as static so that you have only one instance of each object created for the lifetime of your application. 但正如SLaks所提到的,如果同时在内存中存在许多控件实例,那么将画笔和笔创建为静态是一个好主意,这样在应用程序的生命周期中只创建每个对象的一个​​实例。

I really depends on what are you painting. 我真的要看你画的是什么。 If you will paint something that is repainted only as a result of an user interaction, you can loose your performance worries and create all of the graphic objects ad-hoc ie when needed. 如果您将仅在用户交互的情况下绘制重新绘制的内容,则可以消除性能上的担忧,并在需要时即时创建所有图形对象。

Make sure that you Dispose() everything you need in your graphics. 确保在图形中使用Dispose()一切。 Pens, Brushes, Regions, Fonts. 钢笔,画笔,区域,字体。 Those are all GDI objects and are tied into system by GDI handles. 这些都是GDI对象,并通过GDI句柄绑定到系统中。

If you need graphics that is animated in some way or will change in time without user clicking it, prepare all your graphic objects in front and reuse them as much as you can. 如果您需要以某种方式设置动画的图形或在没有用户单击的情况下及时更改图形,请在前面准备好所有图形对象并尽可能多地重复使用它们。 Rule that can be applied here is that is better to waste memory then milliseconds in drawing every frame of the animation. 可以在这里应用的规则是在绘制动画的每一帧时浪费内存然后毫秒更好。

An lastly, at least for this post - don't forget to use double-buffering, either automatic in .net Control system or roll-your-own-back-bitmap style. 最后,至少对于这篇文章 - 不要忘记使用双缓冲,自动在.net控制系统或滚动你自己的后位图样式。

Have fun GDI-ing :) 玩得开心GDI-ing :)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM