PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197
Manual 'MDI Window List' Menu-VBForums
Results 1 to 2 of 2

Thread: Manual 'MDI Window List' Menu

  1. #1

    Thread Starter
    Join Date
    Apr 2007
    The Netherlands

    Manual 'MDI Window List' Menu


    After receiving a few questions about it, I decided to make a codebank submission about how to manually create the well-known "MDI Window List" menu. The menu I'm talking about is simply a list of all currently opened MDI child windows. The checked window is the active window, and by clicking any menu item the corresponding window is activated.

    Now, please not that if you are simply working with MDI forms and you require no special functionality, Visual Studio can do this automatically. If you make your main form an MDI Parent (by setting the IsMdiContainer property to True) and add a MenuStrip control to the form, the Form's MainMenuStrip property is automatically set to that MenuStrip. If you finally create a 'Window' ToolStripMenuItem on that MenuStrip you can assign that menu item to the MenuStrip's MdiWindowListItem property and Visual Studio will automatically add the windows to that list.

    However, what if you are not working with actual MDI forms but for example with 'fake' MDI forms (like in my Tabbed MDI Editor codebank submission)? Or what do you do if you want an extra MenuItem after the Window List (like the "Windows..." menu item in Visual Studio itself)? If you use the automatic method the windows are added to the bottom automatically, as far as I know there is nothing you can do about that.

    So, the only way to overcome that is to create your own MDI window list, and it's not even that hard!

    I'm going to try to explain what is happening exactly, and there is a [VS 2008] example project attached so you can have a look.

    First of all, we need a method that refreshes the window list with changes in the forms (text, number of forms etc). This method will be called right before the Window DropDown is opened so it is always up to date.
    I have called it RefreshWindowList. Code:
    1. Private Sub WindowToolStripMenuItem_DropDownOpening(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WindowToolStripMenuItem.DropDownOpening
    2.         RefreshWindowList()
    3.     End Sub

    The first step is to remove all the window items that may already be in the list (we don't want duplicate windows do we!). This step is already the most difficult step, because you will have to adjust it to your own needs.
    The problem is that we cannot simply remove all the items in the Window dropdown, because there may be items that we want to keep. For example, in my example project there is a "Close" menu item, a separator and an Extra menu item at the bottom. We don't want to remove them.

    So, to do that, we simply Loop through all the DropdownItems backwards. We then check if the current index is any of the items we don't want to remove, and if it is not, we remove it.
    We loop backwards because we are removing items inside the loop. If we did that while looping forward normally, we would get an Index out of range error. Code:
    1. Dim item As ToolStripItem
    2.         For i As Integer = menuItemWindowCount - 1 To 0 Step -1
    3.             item = Me.WindowToolStripMenuItem.DropDownItems(i)
    5.             If Not (item Is CloseToolStripMenuItem _
    6.                     Or item Is WindowSeparator _
    7.                     Or item Is ExtraItemToolStripMenuItem) Then
    8.                 Me.WindowToolStripMenuItem.DropDownItems.RemoveAt(i)
    9.             End If
    10.         Next
    As you can see, I simply use an If statement to check the current menu item is any of the ones we don't want to remove.

    The next step is to add new menu items for each open MDI child window. We simply loop through all the MDI child windows and create a new ToolStripMenuItem for each window. We set its Text to a number (counter) + the window text.
    Then, we assign the current window to the Tag property of the menu item so we can retrieve it when it is clicked.
    Then, we see if the current window is also the Active window. If it is, we check it.
    Then, we need to add a Click EventHandler to allow the user to Click the items.

    Finally, we Insert it into the Window dropdown items. We need to Insert it instead of Add it, because we still want the Extra menu item to be on the bottom! So we need to insert it into the next-to-last index. If you want to have more menu items behind the window list, you need to insert it into a different position. Code:
    1. If mdiWindowCount > 0 Then
    2.             Dim menuItem As ToolStripMenuItem
    3.             Dim counter As Integer = 1
    4.             ' Add the new window items
    5.             For Each window As mdiForm In Me.MdiChildren
    6.                 'Create new menuitem
    7.                 menuItem = New ToolStripMenuItem
    9.                 'Set the text to for example "2. Windowtext"
    10.                 menuItem.Text = counter.ToString & ". " & window.Text
    12.                 'Set the tag to the current window so we can retrieve it later
    13.                 menuItem.Tag = window
    15.                 'Check the menuitem if this is the currently active window
    16.                 If window Is Me.ActiveMdiChild Then
    17.                     menuItem.Checked = True
    18.                 End If
    20.                 'Add a Click EventHandler to be able to click it
    21.                 AddHandler menuItem.Click, AddressOf WindowMenuItemClicked
    23.                 'Finally add it to the actual menuitem list
    24.                 Me.WindowToolStripMenuItem.DropDownItems.Insert(Me.WindowToolStripMenuItem.DropDownItems.Count - 1, menuItem)
    26.                 'Raise the counter by 1
    27.                 counter += 1
    28.             Next
    29.         End If

    The last step is the create the click eventhandler method which is called when the menu item is Clicked. The 'sender' object can be casted to a ToolStripMenuItem, and its Tag property will be the window we need to activate. Code:
    1. Private Sub WindowMenuItemClicked(ByVal sender As Object, ByVal e As EventArgs)
    2.         'Retrieve the clicked MenuItem from the sender object
    3.         Dim menuItem As ToolStripMenuItem = TryCast(sender, ToolStripMenuItem)
    5.         'Retrieve the corresponding form from the Tag property
    6.         Dim frm As mdiForm = TryCast(menuItem.Tag, mdiForm)
    8.         'Activate it
    9.         If frm IsNot Nothing Then
    10.             frm.Activate()
    11.         End If
    12.     End Sub

    Note that we don't need to check the menu item here for example, because as soon as you click it, the dropdown closes. The next time you open it, the RefreshWindowList method will be called again and the correct item will be checked.


    So, that's that! If there are any questions or suggestions, don't hesitate to ask, but not after looking at the code and its comments, you might learn a lot from that!

    Note that, if the reason that you are creating the list manually is because you are not using Mdi Forms but for example TabPages, you will have to replace some things in the code. For example, the active window using Mdi forms is just "Me.ActiveMdiChild" but if you're using TabPages it is different... If you can't figure it out, just ask!

    Attached Files Attached Files

  2. #2
    New Member
    Join Date
    Oct 2008

    Re: Manual 'MDI Window List' Menu

    Very good approach.
    Just want to add some comments that will simplify the code for someone who just need to update the text of any menu in 'Window' for opened MDI child forms. If you do not require to have any other menus or separators in 'Window' you can use this code in your MDI container form:

    This is C# code but you can converted using this tool:

                /// <summary>
                /// DropDownOpening event handler
                /// </summary>
                /// <param name="sender"></param>
                /// <param name="e"></param>
                private void mnuMainWindow_DropDownOpening(object sender, EventArgs e)
                   //update item in window list
                /// <summary>
                /// Helper subroutine to update menu in Window menu
                /// </summary>
                private void RefreshWindowList()
                    //Active form
                    Form frmActiveForm;
                    //Get active mdi form
                    frmActiveForm = this.ActiveMdiChild;
                    //itterate through dropdownitems
                    foreach (ToolStripMenuItem item in mnuMainWindow.DropDownItems)
                        //if item is being checked - the latest mdi form has been opened
                        if (item.Checked)
                            item.Text = frmActiveForm.Text;

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts


Click Here to Expand Forum to Full Width