What is a Multiple Document Interface?
A multiple document interface (MDI) is a graphical user interface in which multiple windows reside under a single parent window. Such systems often allow child windows to embed other windows inside them as well, creating complex nested hierarchies. This contrasts with the single document interfaces (SDI) where all windows are independent of each other.
Advantages of Multiple Document Interface
- With MDI, a single menu bar and/or toolbar is shared between all child windows, reducing clutter and increasing efficient use of the screen space.
- An application's child windows can be hidden/shown/minimized/maximized as a whole.
In this article, we will see how to create Multiple Document Interface in C#. We chose C# because it is one of the most popular programming languages. So, let’s start.
Creating the application
- In Visual Studio, click on Start->New->Project.
- Select Windows Forms Application from the available options.
- Let’s give the application a name. I named it “MDIAppwithRichTextBox”.
- Click on the “OK” button. A Windows.Forms application is created.
- Right-click on the “Form1” in the design view and click on "Properties".
- On the Properties window, scroll down to “Design” and change the “Name” property to “MDIContainer” from “Form1”.
Now, in the Properties window, scroll down to “Window Style” section and change the “IsMdiContainer” property to “true”. The change of the client area of the form changes to grey after doing this. This property tells the program that the form can contain other forms.
- Now, let’s add another form to the project. For that, right-click on the Project in Solution Explorer and select "Add" from the context menu.
- Click on “Windows Form”. A window will appear.
- Let’s name the form at the bottom of this window to “MyForm”.
- Click on the “Add” button. A new form will be added to your project. This form will act as our edit area and will be contained in the MDIContainer form. We will shortly see how.
- First, let’s add a RichTextBox to “MyFrom” form. From the toolbox, let’s drag and drop a RichTextBox to this form and go to the properties of the Richtextbox.
- Scroll down to “Layout” section and change the “Dock” property to “Fill”.
You will see that RichTextBox fills the entire client area of the form.
- Now, let’s go to the first form “MDIContainer” and add a “MenuStrip” from the Toolbox-> Menus & Toolbars to the form.
- You will see that a new text box appears at the top of the form within a strip. Now let’s create the menu. In the first Box type “File”.
- A textbox will appear below it. Let’s create four submenu items. “New File”, “Open File”, “Save” and “Exit”.
- Now, let’s create another topmost menu besides file. On the right of “File”, you will see another textbox.
- Type “Insert” there and below that let’s create two submenus-“Text” and “Image”.
- Now, let’s create another topmost menu.
- On the right of “Insert” menu option, type “Edit”.
- Below “Edit”, let’s create 7 submenus: “Undo”, “Redo”, “Mark Text”, “ForeColor”, “Font”, “Current Color”, “Current Font”, ”Cut”, ”Copy”, and “Paste”.
- At last, let’s create another Menu item -> “CloseActiveForm”.
This ends our menu section.
Now, let’s double click on File->New File. This will create a new method in the code behind file.
- private void newToolStripMenuItem_Click(object sender, EventArgs e)
- {
- }
In this method, let’s add the following code.
- private void newToolStripMenuItem_Click(object sender, EventArgs e)
- {
- MyFrom childform = new MyFrom();
- childform.MdiParent = this;
- childform.Show();
- }
Now, examine the code. The first line reads -
- MyFrom childform = new MyFrom();
It creates a new instance of “MyForm” form which we added to the project.
The second line is -
- childform.MdiParent = this;
It sets the MdiParent property of the instance of “MyForm”. We have set the MDIparent of this form to “this’ which is the current form -(“MDIContainer”) form.
The last line is -
This opens MyForm. This will open inside the client area of “MDIContainer” form.
Let’s run the application and check it. In the running form, click on the “File >> New File” menu. It will open a form. You can click on “New File” many times and it will open multiple forms. Try writing in the form. You will see that you are able to write in any of the opened forms (which, in fact, are instances of “MyForm” which we added to the project).
Now, let’s write the code for opening a new file. The files which can be opened in Richtextbox can either be text files or a “*.rtf” rich text file. So, let’s drag and drop an “OpenFileDialog” to “MDIContainer” form from Toolbox->Dialogs. Now, double click on the second submenu under “File”, i.e., “Open File”. A new method will be generated in the code behind.
- private void openToolStripMenuItem_Click(object sender, EventArgs e)
- {
- }
In this method, let’s add the following code.
- private void openToolStripMenuItem_Click(object sender, EventArgs e)
- {
- openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
- openFileDialog1.RestoreDirectory = true;
- openFileDialog1.Filter = "Text Files (*.txt)|*.txt| Rich Text Format (*.rtf)|*.rtf|" + "All Files (*.*)|*.*";
- if (openFileDialog1.ShowDialog() == DialogResult.OK)
- {
- String fileName = openFileDialog1.FileName;
- if (fileName.Length != 0)
- {
- try
- {
- MyFrom childform = new MyFrom();
- childform.OpenFile(openFileDialog1.FileName);
- childform.MdiParent = this;
- childform.Show();
- }
- catch
- {
- MessageBox.Show(String.Format("{0} is not " + "a valid file", fileName), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- }
- }
- The first line sets the directory to open by default when the openFile dialog opens. We have set it to “MyDocuments” folder.
- The second line sets the default directory when closing File dialogue, i.e., it will be set to the current directory you have used while opening the file.
- The third line sets the filter property of the "Open File" dialog. We have set three types *.txt , *.rtf, and *.*. These three types of files will be shown in the openFile dialog when you try to open any file.
- The fourth line tries to open the openFile dialog and if the result is “OK”, the code in the following section will be executed.
- In the try catch block, let’s add code to open a new instance of “MyForm”. I have added a new method “OpenFile(stringfileName)” in the code behind in “MyForm” which is to read the file provided by “MDIContainer” Form into its richtext box. We will see it soon.
- Here, we have called its “OpenFile” method and passed the file name with full path, which we will select in the openFile dialog.
- In the catch block, we have added a message box to show the error encountered.
Now, let’s examine the “OpenFile” method we have added in “MyForm”.
- public void OpenFile(string fileName)
- {
- string strExt;
- strExt = System.IO.Path.GetExtension(fileName);
- strExt = strExt.ToUpper();
- if (strExt == ".RTF")
- {
- richTextBox1.LoadFile(fileName, RichTextBoxStreamType.RichText);
- }
- else if(strExt == ".TXT")
- {
- richTextBox1.LoadFile(fileName, RichTextBoxStreamType.PlainText);
- }
- else
- {
- System.IO.StreamReader txtReader;
- txtReader = new System.IO.StreamReader(fileName);
- richTextBox1.Text = txtReader.ReadToEnd();
- txtReader.Close();
- txtReader = null;
- richTextBox1.SelectionStart = 0;
- richTextBox1.SelectionLength = 0;
- }
- richTextBox1.Modified = false;
- this.Text = "Editor: " + fileName;
- }
First, we get the extension of file we are going to open. If it is a *.rtf file, it will be opened with the following options.
- richTextBox1.LoadFile(fileName, RichTextBoxStreamType.RichText);
If it is a *.txt file, it will be opened with the following options.
- richTextBox1.LoadFile(fileName, RichTextBoxStreamType.PlainText);
Otherwise, we use the System.IO.StreamReader to read the file.
Lastly, we set the title text of the form to the filename.
- this.Text = "Editor: " + fileName;
Try testing the application and opening a file.
Now, let’s see the code for saving the file.
For that, let’s drag and drop a “SaveFileDialog” to “MDIContainer” form. Now, double-click on the “Save File” submenu. The method will be generated in the code behind. Let’s add the following code to it.
- private void saveToolStripMenuItem_Click(object sender, EventArgs e)
- {
- saveFileDialog1.Filter = "Text Files (*.txt)|*.txt|RTF Files (*.rtf)|*.rtf|All Files(*.*)|*.*";
- saveFileDialog1.AddExtension = true;
- if (saveFileDialog1.ShowDialog() == DialogResult.OK)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- string extension = System.IO.Path.GetExtension(saveFileDialog1.FileName);
- if (extension.ToLower() == ".txt")
- RichtxtEditor.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
- else if(extension.ToLower()==".rtf")
- RichtxtEditor.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.RichText); }
- }
- }
- }
The first line sets the filter for file types to be saved as. The second line is -
- saveFileDialog1.AddExtension = true;
This sets the AddExtension property to true . It adds an extension according to the file type selected in saveFile dialog if it is omitted.
The next line reads -
- if (saveFileDialog1.ShowDialog() == DialogResult.OK)
It opens the saveFile dialog if the dialog result is OK.
The next line is -
- Form activeChildForm = this.ActiveMdiChild;
It is used to get the active child form (active MyForm in our case).
The next line reads -
- if (activeChildForm != null)
- {
It checks if there is an active child form.
In the next line, we get the Richtextbox of the active child form,
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
The next line checks if the Control(RichTextBox) is available.
- if (activeChildForm != null)
The next line gets the extension of file.
- var extension = System.IO.Path.GetExtension(saveFileDialog1.FileName);
The next line checks the extension of the file and saves it accordingly.
- if (RichtxtEditor != null)
- {
- string extension = System.IO.Path.GetExtension(saveFileDialog1.FileName);
- if (extension.ToLower() == ".txt")
- RichtxtEditor.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
- else if(extension.ToLower()==".rtf")
- RichtxtEditor.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.RichText); }
- }
Now, let’s try to insert an image and some text.
For inserting text, let’s double click on the “Text” submenu under “Insert” menu. A new method will be generated in the code behind. Let’s add the following code to it.
- private void textToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- DataFormats.Format myFormat = DataFormats.GetFormat(DataFormats.Text);
-
- if (RichtxtEditor.CanPaste(myFormat))
- {
- RichtxtEditor.Paste(myFormat);
- }
- }
- }
- }
As previously, we get the active richtextbox; then set the data format which can be set to access the text on clipboard. Then, paste the text to the richtextbox.
Now, let’s add the code for inserting an image into the rich text box. Let’s double click on the “Image” submenu under the “Insert” menu. A stub code will be generated in the code behind. Let’s write the following code to it.
- private void imageToolStripMenuItem_Click(object sender, EventArgs e)
- {
- openFileDialog1.Title = "Insert Image";
- openFileDialog1.DefaultExt = "bmp";
- openFileDialog1.Filter = "Bitmap Files|*.bmp|JPEG Files|*.jpg|GIF Files|*.gif|PNG Files|*.png";
- openFileDialog1.FilterIndex = 1;
-
- if (openFileDialog1.ShowDialog() == DialogResult.OK)
- {
- if (openFileDialog1.FileName == "")
- {
- return;
- }
-
- try
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- string theImagePath1 = openFileDialog1.FileName;
- Image img;
- img = Image.FromFile(theImagePath1);
- Clipboard.SetDataObject(img);
- DataFormats.Format df;
- df = DataFormats.GetFormat(DataFormats.Bitmap);
- if (RichtxtEditor.CanPaste(df))
- {
- RichtxtEditor.Paste(df);
- }
- }
- }
- }
- catch
- {
- MessageBox.Show("Unable to insert image.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- }
The first line sets the title for openFile dialog. We have seen the filter in earlier openFile dialog so that’s understood. We come directly to the highlighted code, i.e.,
string theImagePath1 = openFileDialog1.FileName;
Here, we get the full path of the image file selected in openFile dialog.
In the next line, i.e.,
- Image img;
- img = Image.FromFile(theImagePath1);
We get the image form where we declare an image file and set the image in it. In the next line, we set it on the clipboard of Windows so that we can paste it from there.
- Clipboard.SetDataObject(img);
The next lines are obvious. We use these as we have done in the Paste text earlier.
- DataFormats.Format df;
- df = DataFormats.GetFormat(DataFormats.Bitmap);
- if (RichtxtEditor.CanPaste(df))
- {
- RichtxtEditor.Paste(df);
- }
Now, let’s write the code for the Edit menu’s submenus. First, let’s write the code for “Undo” submenu. Double-click on the “Undo” submenu. The code will be generated in the code behind. Let’s write the following code.
- private void undoToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (RichtxtEditor.CanUndo)
- {
- activeChildForm.SuspendLayout();
- RichtxtEditor.Undo();
- activeChildForm.ResumeLayout();
- }
- }
- }
- }
Here, we call the suspendlayout method of the active child form. This suspends the layout of the form. Then we call the undo method of richtextbox and then we resume the layout.
Similarly, for Redo.
- private void redoToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (RichtxtEditor.CanRedo == true)
- {
- if (RichtxtEditor.RedoActionName != "Delete")
- {
- activeChildForm.SuspendLayout();
- RichtxtEditor.Redo();
- activeChildForm.ResumeLayout();
- }
- }
- }
- }
- }
We call the “Redo” method of the richtextbox.
Next, we will see the mark text menu option for coloring the background of the selected text.
- First, let’s add “colorDialog” to the “MDIContainer” Form.
- Let’s go to Toolbox->Dialogs->colorDialog and double click on it.
- Double click on “Mark Text” submenu option under “Edit” menu in “MDIContainer” form. A stub code will be generated in the code behind.
- Let’s write the following code in it.
- private void markTextToolStripMenuItem_Click(object sender, EventArgs e)
- {
-
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (colorDialog1.ShowDialog() == DialogResult.OK)
- {
- if (RichtxtEditor.SelectionLength > 0)
- {
- RichtxtEditor.SelectionBackColor = colorDialog1.Color;
- RichtxtEditor.DeselectAll();
- }
- }
- }
- }
- }
- }
We will see the marked text. The first line is -
- RichtxtEditor.SelectionBackColor = colorDialog1.Color;
Here, we set the backcolor of the selected text to the color of the colorDialog. Then, in the next line, we deselect the text.
Now, let’s see how to set the forecolor of the selected text.
Let’s double click on ForeColor submenu option and in the code behind add the following code.
- private void foreColorToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (colorDialog1.ShowDialog() == DialogResult.OK)
- {
- RichtxtEditor.SelectionColor = colorDialog1.Color;
- RichtxtEditor.DeselectAll();
- }
- }
- }
- }
In the first line, we set the forecolor of the selected text. Then, we deselect all the text.
Now, let’s see how to set the font of the selected text. Drag and drop a fontDialog to the “MDIContainer” form. Now, double-click on the “Font” submenu option. Now, let’s write the following code in the code behind.
- private void foreColorToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (colorDialog1.ShowDialog() == DialogResult.OK)
- {
- if (RichtxtEditor.SelectionLength > 0)
- {
- RichtxtEditor.SelectionColor = colorDialog1.Color;
- RichtxtEditor.DeselectAll();
- }
- }
- }
- }
- }
In the first line, we set the font of the selected text as per the font selected in fontDialog. In the next line, we deselect all the text.
Now, let’s see how to set the current default color of the text.
Let’s double click on the “Current Color” submenu option and go to the code behind and add the following code.
- private void currentTextToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (colorDialog1.ShowDialog() == DialogResult.OK)
- {
- RichtxtEditor.ForeColor = colorDialog1.Color;
- }
- }
- }
- }
Here, in the line RichtxtEditor.ForeColor = colorDialog1.Color; we set the current color of text. This will be the color of the text as we type in some new text.
Now, let’s set the current font of text. Let’s double click on “Current Font” menu option and in the code behind, write the following code.
- private void currentFontToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (fontDialog1.ShowDialog() == DialogResult.OK)
- {
- RichtxtEditor.Font = fontDialog1.Font;
- }
- }
- }
- }
Here, we set the current font of the richtextbox from the fontdialog selection.
Now, let’s see how to “Cut” from richtextbox. Double click on “Cut” submenu option and in the code-behind, let’s write the following code.
- private void cutToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (RichtxtEditor.SelectionLength > 0)
- RichtxtEditor.Cut();
- }
- }
- }
If selection is not zero, we cut the text or image or both.
Similarly, for copy, we double click on the “Copy” submenu and write the following code in the code behind file.
- private void copyToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- if (RichtxtEditor.SelectionLength > 0)
- RichtxtEditor.Copy();
- }
- }
- }
Here, we copy the selection if it is not zero.
For pasting, we double click on the“Paste” submenu and in the code-behind file, we write the following code.
- private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Form activeChildForm = this.ActiveMdiChild;
- if (activeChildForm != null)
- {
- RichTextBox RichtxtEditor = activeChildForm.ActiveControl as RichTextBox;
- if (RichtxtEditor != null)
- {
- RichtxtEditor.Paste();
- }
- }
- }
Here, we paste the cut or copied selection.
Now, to close the currently active Form, we write the following code.
- private void closeActiveFormToolStripMenuItem_Click(object sender, EventArgs e)
- {
- this.ActiveMdiChild.Close();
- }
Now, let’s go to “MyForm” and in its code behind, let’s write the following.
- public MyFrom()
- {
- InitializeComponent();
- this.richTextBox1.EnableAutoDragDrop = true;
- this.richTextBox1.AcceptsTab = true;
- this.richTextBox1.WordWrap = true;
- this.richTextBox1.ScrollBars = RichTextBoxScrollBars.Both;
- this.richTextBox1.ShortcutsEnabled = true;
-
- }
-
- this.richTextBox1.EnableAutoDragDrop = true; this enables drag and drop to Richtextbox
- this.richTextBox1.AcceptsTab = true; this enables tabs
- this.richTextBox1.WordWrap = true; this enables Word wrap according to the width of your form
- this.richTextBox1.ScrollBars = RichTextBoxScrollBars.Both; This enables scrollbars in the richtextbox
- this.richTextBox1.ShortcutsEnabled = true; This enables the shortcut keys in RichTextBox.
The following are the shortcut keys,
- CTRL+Z
- CTRL+E
- CTRL+C
- CTRL+Y
- CTRL+X
- CTRL+BACKSPACE
- CTRL+V
- CTRL+DELETE
- CTRL+A
- SHIFT+DELETE
- CTRL+L
- SHIFT+INSERT
- CTRL+R
Summary
We saw in this article that Multiple Document Interface can be created using Windows.Forms Application. It is easy and very useful because it enables users to work with multiple documents at the same time. MDI applications can be used for a variety of purposes - for example, working on one document while referring to another document, viewing different presentations of the same information, viewing multiple Web sites at the same time, and any task that requires multiple reference points and work areas at the same time. Examples of MDI Applications are,
- Visual Studio
- Adobe Photoshop
- Google Chrome
- Microsoft Word 2003
- Microsoft Excel 2003 etc.
This completes our simple MDI with RichTextBox tutorial. You can play with it and add advanced features like indenting text, bulleting etc. You can check the original application attached to this article.
For reference, you can check the following website,
Thank You!