简体   繁体   中英

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 )

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?

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

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

  • The OnPaint of a control, eg of Form1 , is executed everytime the control is painted (duhh...)
  • The OnPaint of Form1 is executed everytime a child control of Form1 is drawn. 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! 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, 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. 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. Eg 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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