什么是正确的方式来使用的OnPaint在.Net应用程序?应用程序、正确、方式、OnPaint

2023-09-03 08:18:30 作者:-往海的地方北未眠

有时候,我需要控制的定制appearence。还是做风俗画的很多。我知道我可以用的OnPaint 这样做的(见:的http://msdn.microsoft.com/en-us/library/system.windows.forms.control.onpaint.aspx)

Sometimes I need a custom appearence of a control. Or do alot of custom painting. I know I can do so with OnPaint (see: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.onpaint.aspx)

什么是正确的方式来定制油漆的东西上使用您的.NET应用程序的OnPaint ?在那里我必须牢记,以保持我的应用程序进行了优化,并保持渲染时间降至最低?任何规则

What is the right way to custom paint stuff on your .net application using OnPaint? Are there any rules I have to keep in mind to keep my application optimized, and keep render time to a minimum?

注:我看见了,经验丰富,有很多的OnPaint的低效使用,不时,所以我创造了这个Q&放大器; A

Note: I have seen, and experienced, a lot of inefficient uses of OnPaint from time to time, therefore I created this Q&A.

推荐答案

要使用的OnPaint 有效,你必须知道两件事情:

To use OnPaint efficiently you have to know a couple things:

的OnPaint A控制的,例如对 Form1中,则每次执行的控制是画(duhh ...) 的的OnPaint Form1中绘制。例如如果你画一个圆点 Form1中的右上角使用的OnPaint Form 1的,而你对 Form1中 150子控件,该点会被抽至少150倍!它增加了渲染时间大大。特别是如果你自定义绘制和计算的的OnPaint 的很多。 所以按照规则,你必须永远都在的OnPaint 控制的任何逻辑,当控制有一个或多个子控件。相反,你应该做一个自定义的控制,持有它没有更多的子控件,一个执行的油漆工作。和地点,作为对那些需要自定义图形中的位置的父控件的子控件。 当一个控件添加到父,父将重新绘制。如果你想放置控件很多在另一个控制,如大型结果与复选框的 Form1中设置,你必须使用 Form1.SuspendLayout()(见的http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout.aspx)之前,您要添加的子控件。而 Form1.ResumeLayout()当您完成添加控件。这将暂时苏presses的的OnPaint 事件和减少渲染时间。 在透明胶片随时增加渲染时间。 放置元件以这样的方式,存在于他们之间没有任何的背景,降低了的OnPaint 在父控件事件的数量。例如。放置4文本框下方的海誓山盟,让他们thouch海誓山盟。因此在他们与对照组之间没有后台都画在一个的OnPaint 事件,而不是4 的OnPaint 事件。当然,这并不总是可能的,你不希望并排胶所有组件的一面。但它是值得做的,如果性能比外表更重要,例如在somekind的大自定义数据网格。 永远不会改变位置或在的OnPaint 事件控件的大小,因为这将调用新的的OnPaint 事件。如果你必须重新定位/缩放控件,您必须添加其他地方在code时,的OnPaint 被调用之前。例如,地方搬迁/调整code。在 OnLayout onResize受到或类似的活动。如果你还认为你必须把此项搬迁/调整code。在的OnPaint 事件,以便为您的应用程序的工作,比你错了,你需要修改你的code中的逻辑。 在控制调用刷新()它自己的类之外之前想想System.Math.Pow(2,2)次。如果你有冲动打电话刷新你可能需要新的事件和事件处理程序保持同步与你愿意来显示。这也是的Invalidate()的情况下 要检查是否要绘制effenciently你可以做到以下几点。 1.打开你的应用程序2.把制动点的OnPaint在最上面的父3. Maxamize所以它涵盖了您的应用程序的窗口。 4.再次最小化的窗口,您的应用程序将被重新绘制控制控制。如果事情被吸引双人,你已经在你的应用程序的逻辑,犯了一个错误。 The OnPaint of a control, e.g. of Form1, is executed everytime the control is painted (duhh...) The OnPaint of Form1 is executed everytime a child control of Form1 is drawn. e.g. If you draw a dot in the upper right corner of Form1 using the OnPaint of Form1, while you have 150 child controls on Form1, the dot will be drawn at least 150 times! It increases render time drastically. Especially if you do alot of custom drawing and calculations in the OnPaint. So as a rule you must never have any logic in the OnPaint of a control, when that control has one or more child controls. Instead you should make a custom control, which holds no more child controls on it, that does the paint job. And place that as a child control on the parent control on the location where the custom drawing is needed. Whenever a control is added onto a parent, the parent will redraw. If you would place alot of controls on another control, e.g. a large result set with checkboxes on Form1, you must use Form1.SuspendLayout() (see: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout.aspx) before you are adding the child controls. And Form1.ResumeLayout() when you are done adding controls. This temporarily supresses the OnPaint event, and decreases render time. Transparencies always increase render time. Placing components in such a way, that there is no background in between them, decreases the number of OnPaint events in the parent control. E.g. place 4 textboxes beneath eachother so that they thouch eachother. So there is no background in between them and the controls are all painted in one OnPaint event instead of 4 OnPaint events. Of course this is not always possible as you do not want to glue all your components side by side. But it is worth to do, if performance is more important than looks, for example in a large custom 'datagrid' of somekind. NEVER change a location or the size of a control in the OnPaint event, as this invokes new OnPaint events. If you must relocate/resize controls, you will have to add that somewhere else in your code, before the OnPaint is invoked. For example, place relocation/resizing code in the OnLayout or OnResize or similar events. If you still think you must place that relocation/resizing code in the OnPaint event in order for you application to work, than you are wrong, and you need to revise the logic of your code. Think System.Math.Pow(2, 2) times before calling Refresh() on a control outside of its own class. If you have the urge to call Refresh you are probably in need of new events and event handlers to stay in sync with what you are willing to display. This is also the case for Invalidate(). To check if you are drawing effenciently you can do the following. 1. Open you application 2. put a brake point on OnPaint in the Top Most parent 3. Maxamize a window so it covers your application. 4. Minimize the window again and you application will redraw control by control. If things are drawn double, you have made a mistake in the logic of you application.

嗯,我想这就是全部,如果事情想到,我忘了,我会更新这个Q&安培; A。如果我忘了的东西,或者我犯了一个错误,我会很高兴地注意到它!

Well I guess thats all, if something comes to mind that I forgot, i will update this Q&A. If I have forgotten something, or I made a mistake I would be glad to take note of it!

希望这会给别人一个领先的地位在.NET中使用自定义的油漆的东西,因为我前一段时间在寻找这些信息。

Hopefully this will give someone a headstart in using custom paint stuff in .Net, as I was looking for this information some time ago.