hobster
asked on
Resizing form causes flicker/flashing
Has anybody experience flickering when the form is being resized, minimized, or maximized? Very frustrating.
private void frmMain_Resize(object sender, System.EventArgs e)
{
this.Width = this.Height * 2;
}
private void frmMain_Resize(object sender, System.EventArgs e)
{
this.Width = this.Height * 2;
}
ASKER
One of the requirements is that the user must be able to resize the form. When that happens, all the controls in it get resized also.
When it's resized, there is flicker. This is not the big problem. The big problem is when I minimize the form, then restore it, it flickers alot and then half the form disappears. If I minimize and then restore a 2nd time, you see the whole form. The same problem happens if I maximize the form.
When it's resized, there is flicker. This is not the big problem. The big problem is when I minimize the form, then restore it, it flickers alot and then half the form disappears. If I minimize and then restore a 2nd time, you see the whole form. The same problem happens if I maximize the form.
Does this flicker happen if you comment that code out of the resize event handler, and do you have Windows Animations turned on ?
ASKER
If there's nothing inside the Resize event handler, then there's no flicker. How do I know if I have the animation turned on? I checked the form's properties and couldn't find anything related to it.
I think its in other OSs too but I know how to fix it XP
Bring up the System properties, Go to Advanced and then choose Performance settings. At the top of the list is a check box that says Animate windows when minimizing and maximizing, try unchecking that and putting your code back in.
Because windows animates the frame as its restored, it actually resizes it a number of times, I suspect that because your code is overriding the normal resize and triggering a resize at the same time that windows is resizing your form, it's giving GDI a headache.
Bring up the System properties, Go to Advanced and then choose Performance settings. At the top of the list is a check box that says Animate windows when minimizing and maximizing, try unchecking that and putting your code back in.
Because windows animates the frame as its restored, it actually resizes it a number of times, I suspect that because your code is overriding the normal resize and triggering a resize at the same time that windows is resizing your form, it's giving GDI a headache.
Are you specifically trying to maintain a contant aspect ratio for your form (length/width), or are you doing something else in the resize event?
ASKER
I'm using Win2k Server and can't find this setting.
You might need to install this program.
http://www.microsoft.com/ntworkstation/downloads/powertoys/networking/nttweakui.asp
http://www.microsoft.com/ntworkstation/downloads/powertoys/networking/nttweakui.asp
ASKER
I'll have a look at the program.
eternal,
Yes, I'm just trying to resize the form and its controls (buttons, labels, fonts), nothing special. There are a couple of properties that look promising (ex. docking) but after playing with them, I found they weren't adequate. I've searched the web and this flickering problem is pretty prominent but I couldn't find a definite solution.
eternal,
Yes, I'm just trying to resize the form and its controls (buttons, labels, fonts), nothing special. There are a couple of properties that look promising (ex. docking) but after playing with them, I found they weren't adequate. I've searched the web and this flickering problem is pretty prominent but I couldn't find a definite solution.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
eternal,
When I click the Maximize button, the form's controls didn't get resized. Do you know how to get that working? Thanks.
When I click the Maximize button, the form's controls didn't get resized. Do you know how to get that working? Thanks.
Just letting you know I received your post - working on it right now!
Okay, here is the new code! Note that the base.WndProc calls have changed their location because the WM_SYSCOMMAND must be processed by the form BEFORE we try and access the form's size from the FormResized method.
### C#.NET ###
protected override void WndProc(ref Message m)
{
const int WM_EXITSIZEMOVE = 0x232;
const int WM_SYSCOMMAND = 0x112;
switch(m.Msg)
{
case WM_EXITSIZEMOVE: // Form is moved or resized
base.WndProc(ref m);
FormResized();
break;
case WM_SYSCOMMAND: // System command (maximize, minimize, restore, etc.)
base.WndProc(ref m);
const int SC_MAXIMIZE = 0xF030;
const int SC_MINIMIZE = 0xF020;
const int SC_RESTORE = 0xF120;
switch(m.WParam.ToInt32())
{
case SC_MAXIMIZE: // Form is maximized by control
case SC_MAXIMIZE + 2: // Form is maximized by title bar
FormResized();
break;
case SC_MINIMIZE: // Form is minimized by control
//FormResized();
break;
case SC_RESTORE: // Form is restored by control
case SC_RESTORE + 2: // Form is restored by title bar
FormResized();
break;
default:
break;
}
break;
default:
base.WndProc(ref m);
break;
}
}
void FormResized()
{
// Put your code here. This code will be called when
// you form has finished resizing or moving, has been
// maximized, or restored. Remove the comments
// above and it will be called when minimized as well.
// e.g.:
// this.Width = this.Height * 2;
}
###
Just out of curiosity, are you actually controlling the aspect ratio of your form (e.g.: this.Width = this.Height * 2)?
### C#.NET ###
protected override void WndProc(ref Message m)
{
const int WM_EXITSIZEMOVE = 0x232;
const int WM_SYSCOMMAND = 0x112;
switch(m.Msg)
{
case WM_EXITSIZEMOVE: // Form is moved or resized
base.WndProc(ref m);
FormResized();
break;
case WM_SYSCOMMAND: // System command (maximize, minimize, restore, etc.)
base.WndProc(ref m);
const int SC_MAXIMIZE = 0xF030;
const int SC_MINIMIZE = 0xF020;
const int SC_RESTORE = 0xF120;
switch(m.WParam.ToInt32())
{
case SC_MAXIMIZE: // Form is maximized by control
case SC_MAXIMIZE + 2: // Form is maximized by title bar
FormResized();
break;
case SC_MINIMIZE: // Form is minimized by control
//FormResized();
break;
case SC_RESTORE: // Form is restored by control
case SC_RESTORE + 2: // Form is restored by title bar
FormResized();
break;
default:
break;
}
break;
default:
base.WndProc(ref m);
break;
}
}
void FormResized()
{
// Put your code here. This code will be called when
// you form has finished resizing or moving, has been
// maximized, or restored. Remove the comments
// above and it will be called when minimized as well.
// e.g.:
// this.Width = this.Height * 2;
}
###
Just out of curiosity, are you actually controlling the aspect ratio of your form (e.g.: this.Width = this.Height * 2)?
ASKER
Cool, it works. And yes, I am controlling the form's aspect ratio. Thanks very much.
I don't know if this is any help, but I thought the "aspect ratio" was a cool idea for a winform... The problem with this.Width = this.Height * 2, is found when you try and change the Width of the form... nothing happens! I thought we could watch the form and see which direction changed the most (length or width) and then size the form accordingly. Here is what I came up with:
private System.Drawing.Size prevSize;
protected override void OnLoad(EventArgs e)
{
this.prevSize = this.Size;
// OnLoad implementation
base.OnLoad (e);
}
void ExitSizeMove()
{
const double aspectRatio = 2d; // 2:1 aspect ratio
double prevSizeHRatio, prevSizeWRatio;
prevSizeHRatio = (double)this.Height / (double)this.prevSize.Heig ht - 1;
prevSizeWRatio = (double)this.Width / (double)this.prevSize.Widt h - 1;
if(Math.Abs(prevSizeHRatio ) > Math.Abs(prevSizeWRatio))
this.Width = (int)((double)this.Height * aspectRatio);
else
this.Height = (int)(this.Width / (double)aspectRatio);
this.prevSize = this.Size;
}
I also wrote a function to resize a form to a specific aspect ratio with the same area: (This one was my first attempt...)
void SetAspectRatio(double ratio)
{
double x, y;
x = Math.Sqrt(this.Size.Width * this.Size.Height * ratio);
y = x / ratio;
this.Size = new System.Drawing.Size((int)x , (int)y);
}
you can call it like: SetAspectRatio(2d), but I didn't like the way it worked when resizing the form. The only thing that SetAspectRatio would be good for is to call in the OnLoad method BEFORE you initialize your prevSize variable.
private System.Drawing.Size prevSize;
protected override void OnLoad(EventArgs e)
{
this.prevSize = this.Size;
// OnLoad implementation
base.OnLoad (e);
}
void ExitSizeMove()
{
const double aspectRatio = 2d; // 2:1 aspect ratio
double prevSizeHRatio, prevSizeWRatio;
prevSizeHRatio = (double)this.Height / (double)this.prevSize.Heig
prevSizeWRatio = (double)this.Width / (double)this.prevSize.Widt
if(Math.Abs(prevSizeHRatio
this.Width = (int)((double)this.Height * aspectRatio);
else
this.Height = (int)(this.Width / (double)aspectRatio);
this.prevSize = this.Size;
}
I also wrote a function to resize a form to a specific aspect ratio with the same area: (This one was my first attempt...)
void SetAspectRatio(double ratio)
{
double x, y;
x = Math.Sqrt(this.Size.Width * this.Size.Height * ratio);
y = x / ratio;
this.Size = new System.Drawing.Size((int)x
}
you can call it like: SetAspectRatio(2d), but I didn't like the way it worked when resizing the form. The only thing that SetAspectRatio would be good for is to call in the OnLoad method BEFORE you initialize your prevSize variable.
You always get a certain amount of flickering, depending on how many widgets the form has, or if you are overriding the paint method, or you have any ownerdrawn components.
Instead of have that code in your resize eventhandler, why not simply set the frameborder to Fixed3D or FixedSingle ?