Skinned C# form with huge black flicker while resizing!

I'm trying to create some skinned forms (just the border and caption) with a different approach than you usually see but I'm having some issues with form flickering while I resize the form.

I don't know how else to explain the problem, so here's a video I created to demonstrate the problem: http://www.screencast.com/t/AIqK9Szmz

Also, here's a VS2008 test solution with the whole code that repaints the form borders:http://stuff.nazgulled.net/misc/TestForm.zip

Hope someone can help me get rid of the flicker...

Answers


(This is a Vista-specific solution; it only works when desktop compositing is enabled.)

It looks like Windows initializes the contents of resized forms by copying the pixels on the form's original border over to the new areas. In your case, the new areas are initialized black likely because the form originally had black pixels at its border.

To get rid of the flickering, just keep the rightmost and bottommost line of pixels in the form always set to TransparencyKey -- this will keep the new areas transparent until you get a chance to repaint them. I.e., make the form 1 pixel wider & taller than necessary, and paint the extra pixels transparent.

Example: TransparentForm.zip


That's what I use in my base form's constructor:

this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );

I think the key is the use of "AllPaintingInWmPaint".


If you want to make your form have a irregular shape you will have to turn to regions (if you can easily define your form's region using geometric shapes like Circle and Rectangle). Create a System.Drawing.Graphics.Region object and add shapes to it. I think the property on the form is called Region - assign to it your region that you created.

Your other option is to use layered windows. Somebody has done all the work for you. Layered windows do not work on versions of Windows older than 2000, but they have the added benefit of being semi-transparent.

Your final option is to use WPF and set AllowsTransparency="True" WindowStyle="None". That will remove the chrome (Google "chromeless window WPF" for like a million examples).

Finally if you are brave and patient you could always capture the desktop behind your window and paint it before anything else. You will need to resort to some fancy hackery if your window moves: I don't really recommend this approach - but you need to know all your options.


You'll have to give up on using the Form.TransparencyKey property if you want to avoid the ugly uninitialized black video overlay flicker. It doesn't do anything useful in your sample program.


Tried enabling DoubleBuffering ?


Oh, and by the way, using SLIMcode's code won't work unless you put all your paint logic in override OnPaint(). If this doesn't sound familiar you probably don't know that you can forcefully ask for a repaint by calling Invalidate() on your form. It's a mission to refactor your code into a single Paint method - but it results in cleaner code in the end.


To get rid of the flicker while resizing the win form, suspend the layout while resizing. Override the forms resizebegin/resizeend methods as below.

protected override void OnResizeBegin(EventArgs e) {
    SuspendLayout();
    base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
    ResumeLayout();
    base.OnResizeEnd(e);
}

This will leave the controls intact (as they where before resizing) and force a redraw when the resize operation is completed.


Need Your Help

.htaccess 301 remove folder by position

apache .htaccess mod-rewrite redirect

I need to set up some 301 redirects between links residing on the same domain.

Breaking up PHP Websites

php

I am wondering how I can break up my index.php homepage to multiple php pages (i.e. header.php, footer.php) and build a working index.php page using those separate php pages. I know WordPress uses...