tags:

views:

88

answers:

3

My application has the following UI configuration:

The main form is an MDI container. Its child forms are attached to a TabStrip.

Each user has his set of child forms. Depending on the active user, only that user's child forms are displayed, together with tabs.

This is achieved by going through the main form's MdiChildren and setting their Visible property to false/true depending on the active user.

        foreach (Form item in MdiChildren)
        {
            if (((OfficeFormEx)item).UserID == (int)e.NewTab.Tag)
            {
                item.Visible = true;
            }
            else
            {
                item.Visible = false;
            }
        }

This has two undesired effects. One is that every child form gets redrawn in succession, which is ugly and slow. The other is that for some reason the forms go from maximized to normal, effectively undocking them from the main form.

Is there any way to display just one of the child forms, such as the one the user was previously looking at, and get the others to stay in the background? The maximize/normal thing is not that big a deal because I can maximize them again manually.

+1  A: 
Will Marcouiller
Neither helps, unfortunately.
dandan78
Then please, in order to help us help you, provide some code example of what you're doing to check what MdiChild to make visible, etc. Consider that Mdi applications generally don't have all of the possible MdiChildren loaded and opened at application start. If understand correctly, perhaps letting the user open what MdiChild she/he needs would be advisable.
Will Marcouiller
I just added the code. In this case all possible MDI Children are loaded at all times as each user has a fixed number of forms used to display various parts of the app. When the active user changes, the user needs to see only his subset of forms.
dandan78
Unfortunately, unloading the forms that aren't being shown is not an option. The LINQ (.NET 3.5) code is slightly faster than my foreach version and all in all, the speed is close to being acceptable. Looks like the inherent limitations of MDI mentioned by Hans Passant are the remaining obstacle. I appreciate your effort, thanks.
dandan78
Thanks for letting me know. That is pretty much appreciated. =)
Will Marcouiller
+2  A: 

Your question isn't very clear without a code snippet. You are however doing battle with the Windows MDI implementation. One thing it doesn't support is hiding a child window, it can only be minimized at best. Windows Forms implements the Visible property by destroying the Window handle, recreating it when the Visible property is set to True again. That new instance of the window won't be maximized.

It also doesn't support switching the focus to a child window when the current one is maximized. WF's workaround for that is to force the active child window back to the Normal state.

The MDI model is simply not very suitable for displaying child windows in the maximized state. To get a tabbed interface, use a TabControl and display UserControls on its tab pages.

Hans Passant
Sorry if I left out important details, but I really didn't see any point in including a foreach loop. :) The rest of your comment about MDI pretty much sums up what I've been deailng with. :( However, I could swear that some of this worked in one of my previous projects. I'll have to take a look. Thanks for the info on what happens under the hood.
dandan78
+1 These are precious information to consider when dealing with MDI apps.
Will Marcouiller
A: 

I eventually solved this one so here's a belated write-up.

Will Marcouiller suggested SuspendLayout() and ResumeLayout(), which did not work. This led me to investigate what these two methods actually do and reach the conclusion that what I needed was a way to stop the main form from redrawing while operations on the MDI children were in progress.

This in turn resulted in the following two static utility methods which suspend redrawing for a given control. In my case, suspending redrawing of the main form resulted in a massive speed up.

/// <summary>
/// suspends drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void SuspendDrawing(Control control)
{
    SendMessage(control.Handle, WM_SETREDRAW, false, 0);
}

/// <summary>
/// resumes drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void ResumeDrawing(Control control)
{
    SendMessage(control.Handle, WM_SETREDRAW, true, 0);
    control.Refresh();
}
dandan78