Link to home
Start Free TrialLog in
Avatar of hobster
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;
}
Avatar of trojan2k
trojan2k

Hi,

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 ?
Avatar of hobster

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.
Does this flicker happen if you comment that code out of the resize event handler, and do you have Windows Animations turned on ?
Avatar of hobster

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.
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?
Avatar of hobster

ASKER

I'm using Win2k Server and can't find this setting.
Avatar of hobster

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.
ASKER CERTIFIED SOLUTION
Avatar of eternal_21
eternal_21

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of hobster

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.
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)?
Avatar of hobster

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.Height - 1;
      prevSizeWRatio = (double)this.Width / (double)this.prevSize.Width - 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.