WinForms painting – SuspendLayout, dblBuffer etc

WinForms painting – SuspendLayout, dblBuffer etcWinFormspainting-SuspendLayout,dblBufferetc from:http://discuss.joelonsoftware.com/default.asp?dotnet.12.454272.8Hello,(Somecontext…IworkonmoderatelycomplexWinFormsapplicati…

大家好,欢迎来到IT知识分享网。

WinForms painting – SuspendLayout, dblBuffer etc


from:

http://discuss.joelonsoftware.com/default.asp?dotnet.12.454272.8

Hello,

(Some context… I work on moderately complex WinForms applications, eg many screens, with complex user controls that compose infragistics with common controls etc, plus a fair bit of background processing (mostly via BackgroundWorkers).  I don’t use any true custom controls with fully manual painting.)

I routinely run into problems with rendering, particularly:

1) slow rendering

2) rendering process is visible to user.

3) flicker during appForm resize and other situations.

My main issue is that I haven’t found a way to fully suspend drawing on a Form or User control that will halt all drawing/layout events on all user-controls and child controls?

DoubleBuffering – seems to only affect the one control and doesn’t help with the rendering of children.

SuspendLayout – doesn’t halt painting, only the Layout.

Any suggestions appreciated.

Mike Liddell
Send private email

Tuesday, February 20, 2007

 

 

Play with the SetStyle setting on various controls ( especially DoubleBuffering, AllPaintingInWmPaint and UserPaint ( don’t know how well UserPaint will work for you ).

Play with these settings on your various controls and see how that works.


Wednesday, February 21, 2007

 

 

Here is a specific scenario to consider

The application form has a wizard-like container control that can host multiple pages.  Each page is a rich UserControl with complex and nested child controls.

The wizard-container is showing the first page (visible, dock-fill), and the second-page is hidden (visible=false, enabled=false, and/or not even in the controls list).

 

=> How would you transition from page1 to page2 to acheive slick rendering.  In particular, the nicest result is probably a short pause (no visual change to page1) while work is done, then ‘pop’ the new screen is fully rendered.

=> I find this scenario very hard to get right in general and every application that does this sort of thing has to be custom-fiddled to get a nice result.  I often test variations of orderings of Update/Refresh/BringToFront/Hide/Show and the results are often very suprising (eg change one minor ordering and the visual outcome is drastically different).  Sometimes I try manual rendering of the entire control (including all child controls) to back-buffer, but I haven’t had any success with that so far.

How do other people with this scenario?

Any suggestions appreciated.

Mike Liddell
Send private email

Wednesday, February 21, 2007

 

 

> Sometimes I try manual rendering of the entire control (including all child controls) to back-buffer, but I haven’t had any success with that so far.

I don’t know what you’ve done and haven’t tried anything like this myself, but here’s a guess.

When a control isn’t visible (e.g. when it’s hidden behind another) then the standard OnPaint doesn’t work, because the associated Graphics region (which paints to the screen) is clipped.

What you might be wanting to try, therefore, is draw to a non-screen Graphics object, which you can then blit to the screen.

The example shown in the help for the BufferedGraphics class might help you do that.

I don’t know how to use BufferedGraphics to buffer output from standard controls (I can see how to do it from custom controls). Maybe it means implementing a MyRender method in your form, which constructs a PaintEventArgs using a Graphics instance obtained from a  BufferedGraphics instance, and which invokes the OnPaint method of the various controls in the form (passing your own PaintEventArgs instance to the controls’ OnPaint methods).

FWIW, printing too entails drawing to a non-screen buffer; I’ve never implemented printing so I don’t know whether that works with standard controls (e.g. whether printing persuades them to render to a non-screen Graphics object).

The above is something along the lines of what you’ve been trying, but beware that I’m not confident that this is the best or standard way to do it.

Also I don’t know about “BackgroundWorkers”: does that slow down rendering? A tiny bit of flicker or shimmer is normal (and so, expected and barely noticeable) at the best of times when a screen is refreshed (e.g when you scroll a multi-line edit box); but not a lot of flicker.

Christopher Wells
Send private email

Wednesday, February 21, 2007

 

 

What I wound up doing was to create a user control that ‘drew’ the child controls as graphics images (bitmaps, lines, rectangles, etc).  Then one of two approaches:

1. Place the ‘real’ controls (one at a time) in the normal tab order as the user tranverses the image, redrawing that control to show any changes, or put the ‘real’ control where the user clicked if not folloing the tab order.

2. In the situation where only one record would be live, pop-up a dialgo witht ht real controls and redrraw the image when the dialgo was dismissed, showing the changed data.

stoneyowl

Thursday, February 22, 2007

 

 

Some old fashioned Win32 code might help, if you know when you want to turn updates off and then on:

public void BeginUpdate()

{

  SendMessage( this.Handle, WM_SETREDRAW, 0, 0);

}

public void EndUpdate()

{

  SendMessage( this.Handle, WM_SETREDRAW, 1, 0);

  Parent.Invalidate(true);

}

BillT
Send private email

Thursday, February 22, 2007

 

 

Oh, and you should also check out following:

http://www.syncfusion.com/FAQ/WinForms/

BillT
Send private email

Thursday, February 22, 2007

 

 

Don’t know if you’ve already run into this, but one thing I realized today is that SuspendLayout only suspends layout for the control it’s called on…and _not_ for any of its child controls.  So if you want to SuspendLayout on the control and all its child controls, you have to write a recursive routine to do so.

Fixing this doesn’t solve all the redraw issues, but it can definitely speed things up.

Kyralessa
Send private email

Thursday, February 22, 2007

 

 

I use

 this.SetStyle(ControlStyles.UserPaint |

                ControlStyles.AllPaintingInWmPaint |

                ControlStyles.OptimizedDoubleBuffer, true);

            this.UpdateStyles();

after each constructor and then in the load event I say

this.Visible = true;

this.Update();

Doesn’t really solve it entirely but relieves the pain. On second opening its relatively ok – not so much visible drawing.  The first call is what takes time and from what I gather you can only work around this perhaps by ngening.

Also check performace on a release build.  Things might look a little better also if infragistics controls are running out of GAC it might slow you down a touch.

These 3rd party custom controls carry a penalty one way  or another. I swapped out a combobox I was too lazy to owner draw and the performance change was remarkable.

All the best

by10

Friday, February 23, 2007

 

 

This topic is archived. No further replies will be accepted.

转载于:https://www.cnblogs.com/luoyaoquan/archive/2011/12/26/2301846.html

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/22551.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信