mishamosher
mishamosher

Reputation: 1023

Manage windows inside a panel with a 'Windows'-like menu

I've a panel.

I add WinForms inside it. The WinForms added have the TopLevel and Visible properties set to FALSE and TRUE.

I can do a panel.SetChildIndex(WinForm1,0) to bring WinForm1 to front.

What I've not managed to do is keep a track of the actual ChildIndex of the panel.

The idea is to have buttons that opens forms inside the panel, and that when the panel opens a new button is added in a Windows menu.

Something like when many files are open on a VS Project, you can go to Window menu and select one. Also, if you change the active page by clicking the page, the Window menu auto-updates and checks the actual active page.

I want to do this, but with a panel container. I've managed to get done everithing, but not the the Window menu auto-updates and checks the actual active page part.

Isn't there an event fired when BringToFront() or SetChildIndex(form, index) are called? Any event when I click another form that's inside the panel and it becomes the "active one"? Or some property of the panel that I can keep track of that changes when active form changes?

Upvotes: 1

Views: 981

Answers (2)

mishamosher
mishamosher

Reputation: 1023

Found that when a form inside a panel is closed, the Controls property of the panel gets reindexed, where the index zero is the form that gets the new focus. Now that I've a way to check the form that's in front when I close another one, windows administration in panels is done.

Going to put the source code, maybe it can help someone :)

Please note that I'm using a RadRibbonForm, a standard panel, and RadForms inside the panel. Rad's are from Telerik. Some things should change to make this work on standardWinForms, but the changes are minimal.

Also, I'm not using a menu that shows the forms, I'm using RadButtonElement's in a page of the ribbon menu instead.

AddRadFormWindow must be called to put a window and manage it automatically.

Example of adding a window:

AddRadFormWindow(typeof (MyRadForm))

Now, the source. It must be inside the code of the RadRibbonForm's class.

public static class ExtensionsRadForm
{
    [DllImport("user32.dll")]
    private static extern int ShowWindow(IntPtr hWnd, uint msg);

    public static void Deminimize(this RadForm form)
    {
        if (form.WindowState == FormWindowState.Minimized)
            ShowWindow(form.Handle, 9);
    }
}

    private void RefreshButtonsChecks(string windowName)
    {
        if (windowName != null)
        {
            principalPanel.Controls[windowName].BringToFront();
        }
        if (principalPanel.Controls.Count > 0)
        {
            if (principalPanel.Controls.Cast<RadForm>().Any(radForm => radForm.WindowState != FormWindowState.Minimized))
            {
                foreach (RadItem item in radRibbonBarGroupOpenWindows.Items)
                {
                    var buttonBorder = ((RadButtonElement) item).BorderElement;
                    if (item.Name == panelPrincipal.Controls[0].Name + "Button")
                    {
                        buttonBorder.ForeColor = Color.LimeGreen;
                        buttonBorder.BottomColor = Color.LimeGreen;
                        buttonBorder.TopColor = Color.LimeGreen;
                        buttonBorder.LeftColor = Color.LimeGreen;
                        buttonBorder.RightColor = Color.LimeGreen;
                        principalPanel.Controls[0].Focus();
                    }
                    else
                    {
                        buttonBorder.ForeColor = Color.Transparent;
                        buttonBorder.BottomColor = Color.Transparent;
                        buttonBorder.TopColor = Color.Transparent;
                        buttonBorder.LeftColor = Color.Transparent;
                        buttonBorder.RightColor = Color.Transparent;
                    }
                }
            }
            else
            {
                foreach (RadItem item in radRibbonBarGroupAbiertas.Items)
                {
                    var buttonBorder = ((RadButtonElement)item).BorderElement;
                    buttonBorder.ForeColor = Color.Transparent;
                    buttonBorder.BottomColor = Color.Transparent;
                    buttonBorder.TopColor = Color.Transparent;
                    buttonBorder.LeftColor = Color.Transparent;
                    buttonBorder.RightColor = Color.Transparent;
                }
            }
        }
    }
private void PrincipalPanelLayout(object sender, LayoutEventArgs e)
    {
        RefreshButtonsChecks(null);
    }
private void RadButtonElementCloseAllWindowsClick(object sender, EventArgs e)
    {
        int limitButtons = radRibbonBarGroupOpenWindows.Items.Count;
        for (int index = 0; index < limitButtons; index++)
        {
            RadItem radItem = radRibbonBarGroupOpenWindows.Items[0];
            radItem.Dispose();
        }
        int limitControls = principalPanel.Controls.Count;
        for (int index = 0; index < limitControls; index++)
        {
            Control control = principalPanel.Controls[0];
            control.Dispose();
        }
        Update();
        GC.Collect();
    }
private void AddRadFormWindow(Type windowToAdd)
    {
        if (!principalPanel.Controls.ContainsKey(windowToAdd.Name))
        {
            var window = (RadForm) Activator.CreateInstance(windowToAdd);
            window.TopLevel = false;
            window.Visible = true;
            window.FormClosing += (method, args) =>
                                       {
                                           radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
                                           GC.Collect();
                                       };
            window.Enter += (method, args) => RefreshButtonsChecks(window.Name);
            var closeMenuItem = new RadMenuItem("Close");
            closeMenuItem.MouseDown += (method, args) =>
                                           {
                                               panelPrincipal.Controls[window.Name].Dispose();
                                               radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
                                           };
            var contextMenu = new RadContextMenu();
            contextMenu.Items.Add(closeMenuItem);
            var button = new RadButtonElement(window.Text) {Name = window.Name + "Button"};
            button.MouseDown += (method, args) =>
                                    {
                                        switch (args.Button)
                                        {
                                            case MouseButtons.Left:
                                                if (((RadForm) principalPanel.Controls[window.Name]).WindowState ==
                                                    FormWindowState.Minimized)
                                                    ((RadForm) principalPanel.Controls[window.Name]).Deminimize();
                                                principalPanel.Controls[window.Name].BringToFront();
                                                principalPanel.Controls[window.Name].Focus();
                                                break;
                                            case MouseButtons.Right:
                                                contextMenu.Show(MousePosition);
                                                break;
                                        }
                                    };
            radRibbonBarGroupOpenWindows.Items.Add(button);
            principalPanel.Controls.Add(window);
            principalPanel.Controls[window.Name].BringToFront();
            principalPanel.Controls[window.Name].Focus();
        }
        principalPanel.Controls[windowToAdd.Name].BringToFront();
        principalPanel.Controls[windowToAdd.Name].Focus();
        Update();
        GC.Collect();
    }
public Constructor()
    {
        panelPrincipal.Layout += PanelPrincipalLayout;
    }

Upvotes: 1

Amit
Amit

Reputation: 22076

It is taken from here

When Control's ZOrder is chaged layout operation is always performed in control's container control.

When I subscribed to container's Layout event and called BringToFront() it showed me Control that changed its ZOrder(LayoutEventArgs.AffectedControl) and changed property (LayoutEventArgs.AffectedProperty).

Upvotes: 2

Related Questions