views:

860

answers:

3

I have an MDI form with a centered background image.
Each time the user changes the size or state of the form, the image isn't updated at all. It remains in the old place (not centered any more) and is even lost when the form is made too small.

How can this situation correctly be handled?
Do I really have to call "this.Refresh()" in all event handlers related to form size and state?

Application is realized in .net 3.5SP1 C# with Windows.Forms.

A: 

Call PositionContainersToParentMiddle method in Resize event of your MDI form. I have not tested it, but it should work. You might have to put conditions in Resize event to stop Image location change at every resize.

   private void YourMDI_Resize(object sender, EventArgs e)
    {
        PositionContainersToParentMiddle();
    }

    private void PositionContainersToParentMiddle()
    {
        int iInitX = (ParentOfImage.Size.Width - YourImage.Size.Width) / 2;
        int iInitY = ( ParentOfImage.Location.Y + YourImage.Size.Height ) / 2;
        YourImage.Location = new Point( iInitX, iInitY ) ;

    }
Mahin
I'm sure this won't work when the form state changes. As I've written in the question, it must also work when the form is maximized.Also I consider it a bit a lot of code when calling "this.Refresh()" would just do the same...
Marc
@Marc: I have created a new MDI app. Made the MDI full screen. Set one background image on it. Changed its BackGroundImageLayout to Center. executed it. Now I am getting the centered image at center only when I resize the form or change its state. The only problem is it updates itself a bit slow when I resize it very fast. I dont know why it is not working for you.
Mahin
Mahin, thanks for your help. I've also created a new Windows Forms (3.5) app. Defined the form as MDI container, defined a background image, set it to Center and started the application. When I resize the form then the image is not re-centered at all. It's only centered when being maximized as you said. Even worse, the image sometimes appears twice: once in the original position and once centered when maximizing the form.
Marc
@Marc : M just curious... Have you Changed its BackGroundImageLayout to Center.
Mahin
Mahin, yes I've set it to Center. I've done all of this in the designer, there's no user code at all.
Marc
+1  A: 

Unfortunately there doesn't seem to be a super-quick way to do this, but the following is my solution and at least doesn't seem to rely on coincidences.

In the mdi constructor, handle resizing:

this.ResizeEnd += delegate { this.Refresh(); };

And then this override to handle maximize/restore events

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Win32.WM_SYSCOMMAND)
        {
            int test = m.WParam.ToInt32() & 0xFFF0;
            switch (test)
            {
                case Win32.SC_MAXIMIZE:
                case Win32.SC_RESTORE:
                    this.Invalidate();  // used to keep background image centered
                    break;
            }
        }
        base.WndProc(ref m);
    }

Constant values are defined as:

    public const int WM_SYSCOMMAND =                    0x0112;
    //wparam for WM_SYSCOMMAND should be one of these after masking with 0xFFF0:
    public const int SC_RESTORE =                       0xF120;
    public const int SC_MINIMIZE =                      0xF020;
    public const int SC_MAXIMIZE =                      0xF030;
Clyde
Fantastic, this fixes it! BTW in your sample code you should remove the Win32 namespace from the constants otherwise it doesn't work.Thanks a lot!
Marc
Win32 just happens to be the namespace where I've declared those constants. You could put them local in the file, but I like to keep them separated in one global file so they're shared by all the code. It's just one huge list of public const int WM_XXXXXX = 0x00XXX; :-)
Clyde
A: 

You could do all of that, or you could just put a me.refresh in the MDI's resize event.

Joe