Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating Tabbed MDI Form

0.00/5 (No votes)
31 Oct 2008 1  
A tutorial for creating a tabbed MDI form
tabbedMDI.PNG

Introduction

This is a tutorial for creating a tabbed MDI form. With this step, you'll know how easy it is to create a tabbed MDI form.

Background

When I was trying to make a text editor, I found this trick.

Using the Code

I create a second form called frmChild. This is the template form for MDI child. But first, create a Parent form which has: tab container, menu / button to add and delete, menu to browse the tabs. To set Parent form as MDI parent, in properties window, set isMDIContainer = true. You may add menu to list your MDI child, but this is for checking for your MDI children, are they synchronized with tabs or not. Don't forget to set the control of the child form as public if you want that the control can be accessed from the Parent form. Open frmChild.Designer.cs, navigate below "Windows Form Designer generated code" region. You will see something like this:

private System.Windows.Forms.RichTextBox richTextBox1; 

Change the line like this:

public System.Windows.Forms.RichTextBox richTextBox1; 

That's it! From this example, now you can access richtextbox from the Parent form. From the add menu click event, suppose it's called mnuAdd_Click, add new child form and tab, also tab list menu:

	private void mnuAdd_Click(object sender, EventArgs e)
        {
            frmChild newChild = new frmChild();   //add new child
            TabPage childTab = new TabPage();     //create new tab page
            newChild.MdiParent = this;            //set as child of this form
            newChild.Name = "Child" + createdTab.ToString();
            newChild.Text = " Child no " + createdTab.ToString();
            childTab.Name = newChild.Name;     
                     //make sure name and text are same
            childTab.Text = newChild.Text;       
                     //this is for synchronize later
            tabControl1.TabPages.Add(childTab);          //add new tab
            newChild.richTextBox1.Parent = childTab;     //attach to tab
            ToolStripMenuItem newMenuTab = new ToolStripMenuItem();   
                     //create menu to hold tab
            newMenuTab.Text = newChild.Text;                    
                     //make sure the name and text are same to synchronize later
            newMenuTab.Name = newChild.Name;
            mnuTab.DropDownItems.Add(newMenuTab);        //add menu item
            newMenuTab.Click += new EventHandler(newMenuTab_Click); 
                     //add event handler
            tabControl1.SelectTab(childTab);     
             //this is to make sure that tab page is selected in the same time
            newChild.Show();                                 
       //as new form created so that corresponding tab and child form is active
            createdTab++;   //increment of course
        }	

When tab list menu is clicked, you select one tab, you want the corresponding Child form to be activated too.

void newMenuTab_Click(object sender, EventArgs e)
{            
   foreach (TabPage theTab in tabControl1.TabPages)
   {
       if (theTab.Text == sender.ToString ())   //sender is the clicked menu 
       { /*when menu is clicked, activate the corresponding form and tab page*/
          tabControl1.SelectTab(theTab);    /* when menu is clicked, select 
                    tab and activate MDI child*/
          foreach (Form WantToSelect in this.MdiChildren)
          {
             if (WantToSelect.Name == theTab.Name)    /*this is why you must 
	    make sure child form's and tab page's name are same for easier control*/
             {                                                                           
                 WantToSelect.Select();            //activate MDI child
              }
           } 
         }
    }
}

of course, you want the corresponding mdiChild to be selected when you clicked the tab.

private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
  foreach (frmChild  WantToSelect in this.MdiChildren )
  {
    if (tabControl1.SelectedTab != null) /*if no child has created, an error
                                will occur */
    {
       if (WantToSelect.Name == tabControl1.SelectedTab.Name)    /*again, this
 is why you must make sure child form's and tab page's name are same for 
easier control*/
       {                                                                           //
           WantToSelect.Select();  //activate MDI child
       }
     } 
   }
}

The corresponding mdiChild must close when the tab is closed. Suppose the close menu is called mnuClose_Click.

private void mnuClose_Click(object sender, EventArgs e)
{   
   mnuTab.DropDownItems.RemoveByKey(tabControl1.SelectedTab.Name);   
      //this is why you must make sure menu's and tab page's name are same
   this.ActiveMdiChild.Close();                  
      //because of synchronize routine, you must close the form first before tab.
   tabControl1.SelectedTab.Dispose();    
      //if tab first, activated tab will change and so the child form, 
      //this will be the closed form. The wrong form will close....
}

The last thing is the importance of activating the corresponding tab with the Child form. For example, accessing richtextbox properties.

private void lblChar_Click(object sender, EventArgs e)
{
  frmChild childForm = (frmChild ) this.ActiveMdiChild ;  //this is the reason
          //why synchronization between tab and active MDI child is important
  lblChar.Text = "Char : " + childForm.richTextBox1.TextLength.ToString(); 
 
}

Points of Interest

That's just the sample code, actually, I'm not using RichTextBox for my text editor. Instead, I'm using scintilla net wrapper.

History

  • 31st October, 2008: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here