简体   繁体   English

在.Net应用程序中使用OnPaint的正确方法是什么?

[英]What is the right way to use OnPaint in .Net applications?

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 ) 我知道我可以用OnPaint这样做(参见: http//msdn.microsoft.com/en-us/library/system.windows.forms.control.onpaint.aspx

What is the right way to custom paint stuff on your .net application using OnPaint ? 使用OnPaint在.net应用程序上自定义绘制内容的正确方法是什么? Are there any rules I have to keep in mind to keep my application optimized, and keep render time to a minimum? 是否有任何规则需要记住以保持我的应用程序优化,并将渲染时间保持在最低限度?

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您必须了解以下几点:

  • The OnPaint of a control, eg of Form1 , is executed everytime the control is painted (duhh...) 每次控件绘制时都会执行控件的OnPaint ,例如Form1的控件(duhh ...)
  • The OnPaint of Form1 is executed everytime a child control of Form1 is drawn. 每次绘制Form1子控件时 ,都会执行Form1OnPaint eg 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! 例如,如果你在画的右上角点Form1使用OnPaintForm1 ,当你有150个控件Form1 ,该点会被吸引至少150倍! It increases render time drastically. 它大大增加了渲染时间。 Especially if you do alot of custom drawing and calculations in the OnPaint . 特别是如果你在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. 因此,作为规则,当控件具有一个或多个子控件时,控件的OnPaint中绝不能有任何逻辑。 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, eg 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. 如果您将很多控件放在另一个控件上,例如Form1上带有复选框的大型结果集,则必须使用Form1.SuspendLayout() (请参阅: http//msdn.microsoft.com/en-us/library/system。 windows.forms.control.suspendlayout.aspx )在添加子控件之前。 And Form1.ResumeLayout() when you are done adding controls. 完成添加控件后的Form1.ResumeLayout() This temporarily supresses the OnPaint event, and decreases render time. 这会暂时抑制OnPaint事件,并缩短渲染时间。
    • 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. 以这种方式放置组件,它们之间没有背景,减少了父控件中的OnPaint事件的数量。 Eg place 4 textboxes beneath eachother so that they thouch eachother. 例如,将4个文本框放在彼此之下,以便它们互相打开。 So there is no background in between them and the controls are all painted in one OnPaint event instead of 4 OnPaint events. 因此,它们之间没有背景,控件全部绘制在一个OnPaint事件而不是4个OnPaint事件中。 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. 切勿在OnPaint事件中更改控件的位置或大小,因为这会调用新的OnPaint事件。 If you must relocate/resize controls, you will have to add that somewhere else in your code, before the OnPaint is invoked. 如果必须重定位/调整控件大小,则必须在调用OnPaint之前在代码中的其他位置添加控件。 For example, place relocation/resizing code in the OnLayout or OnResize or similar events. 例如,将重定位/调整大小代码放在OnLayoutOnResize或类似事件中。 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. 如果您仍然认为必须将重定位/调整大小代码放在OnPaint事件中以使应用程序正常工作,那么您需要修改代码的逻辑。
    • Think System.Math.Pow(2, 2) times before calling Refresh() on a control outside of its own class . 在对自己的类之外的控件上调用Refresh()之前,请考虑System.Math.Pow(2,2)。 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. 如果您有调用Refresh的冲动,您可能需要新事件和事件处理程序以与您愿意显示的内容保持同步。 This is also the case for Invalidate(). 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. 1.打开你的应用程序2.在最顶级的父级上的OnPaint上放置一个制动点3.最大化一个窗口,使其覆盖你的应用程序。 4. Minimize the window again and you application will redraw control by control. 4.再次最小化窗口,您的应用程序将通过控件重绘控件。 If things are drawn double, you have made a mistake in the logic of you application. 如果事情被画了两倍,那么你在应用程序的逻辑上就犯了一个错误。

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! 如果我忘记了什么,或者我犯了错误,我很乐意留意它!

Hopefully this will give someone a headstart in using custom paint stuff in .Net, as I was looking for this information some time ago. 希望这会让某人在.Net中使用自定义绘画的东西,因为我不久前正在寻找这些信息。

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

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