We will also add Windows menu to our notepad, to create window menu go to following link,
Here's the function "UpdateDocumentSelectorList()" that removes and re adds all elements of treeView1. This function just adds all visible tabs text of TabControl to treeView1.
You just need to call this function once New, Open, or Close action is completed for handling only visible documents.
- public void UpdateDocumentSelectorList()
- {
- TabControl.TabPageCollection tabcoll = myTabControlZ.TabPages;
- treeView1.Nodes.Clear();
- foreach(TabPage tabpage in tabcoll)
- {
- String fname = tabpage.Text;
- Color color = Color.FromArgb(245, 255, 245);
- if (fname.Contains("*"))
- {
- fname = fname.Remove(fname.Length - 1);
- }
- if(fname.Contains("Untitled"))
- {
- color = Color.FromArgb(245, 255, 245);
- }
- else
- {
- color = Color.FromA#fffafa;
- }
-
- TreeNode trnode = new TreeNode();
- trnode.Text = fname;
- trnode.BackColor = color;
- treeView1.Nodes.Add(trnode);
- }
- }
Getting RichTextBox Control from Current Tab in TabControl
When you add a Tab to TabControl and if you want to get the added RichTextBox control from the selected tab, then use the following syntax.
var object=(object)TabControl.TabPages[tabcontrol selected index].Controls[0];
e.g.:
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
Now, you can perform actions on _myRichTextBox which is the selected richTextBox from selected tab in TabControl.
All right, let's move to the main form. Once you have created the Windows Forms Application then add MenuStrip, and SplitContainer. Add TreeView (treeView1) to panel1 and TabControl to panel2 of splitcontainer respectively. Remember you directly cannot add ContextMenuStrip to RichTextBox,rather than you must add ContextMenuStrip to every added RichTextBox to a TabControl. Download the source code for better understanding.
Now, let's see some important functions code.
1. New
This function creates a new Untitled document with tab and will also add this text to treeView1.
- public static int count = 1;
- private void File_New_MenuItem_Click(object sender, EventArgs e)
- {
- MyTabPage tabpage = new MyTabPage(this);
- tabpage.Text = "Untitled " + count;
- myTabControlZ.TabPages.Add(tabpage);
-
- myTabControlZ.SelectedTab = tabpage;
-
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
- _myRichTextBox.richTextBox1.Select();
-
-
- _myRichTextBox.richTextBox1.ContextMenuStrip = myContextMenuStrip;
-
- this.UpdateDocumentSelectorList();
-
- this.Text = "Advanced Notepad in C# [ Untitled "+count+" ]";
-
- FilenameToolStripLabel.Text = tabpage.Text;
-
- UpdateWindowsList_WindowMenu();
-
- count++;
- }
2. Open
This function will open multiple files from selecting files from OpenFileDialog by setting MultiSelect property to true. Let's see the code that creates the tab. Read each file at a time and add that tab to tabcontrol. Also add ContextMenuStrip to RichTextBox.
- private void File_Open_MenuItem_Click(object sender, EventArgs e)
- {
- StreamReader strReader;
- String str;
- if (openFileDialog1.ShowDialog() == DialogResult.OK)
- {
- String[] files = openFileDialog1.FileNames;
- foreach (string filename in files)
- {
- MyTabPage tabpage = new MyTabPage(this);
-
- strReader = new StreamReader(filename);
- str = strReader.ReadToEnd();
- strReader.Close();
-
- String fname = filename.Substring(filename.LastIndexOf("\\") + 1);
- tabpage.Text = fname;
-
-
- tabpage._myRichTextBox.richTextBox1.ContextMenuStrip = myContextMenuStrip;
-
- tabpage._myRichTextBox.richTextBox1.Text = str;
- myTabControlZ.TabPages.Add(tabpage);
- myTabControlZ.SelectedTab = tabpage;
-
-
- this.UpdateDocumentSelectorList();
-
-
-
-
- fname = tabpage.Text;
- if (fname.Contains("*"))
- {
- fname = fname.Remove(fname.Length - 1);
- }
- tabpage.Text = fname;
-
-
- OpenedFilesList.Add(filename);
-
- FilenameToolStripLabel.Text = filename;
- this.Text = "Advanced Notepad in C# [ "+fname+" ]";
- }
-
-
- if (myTabControlZ.SelectedIndex >= 0)
- {
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
- _myRichTextBox.richTextBox1.Select();
- }
- UpdateWindowsList_WindowMenu();
- }
- }
3. Save, Save As, Save All
Well, you know how to save a file. So, we will see only Save All functions for saving all the files at once, without overwriting one file contents to another file contents. See the above image. In status strip, you can see full filename path. Here's the code to save all files one by one.
- private void File_SaveAll_MenuItem_Click(object sender, EventArgs e)
- {
- if (myTabControlZ.TabCount > 0)
- {
- OpenedFilesList.Reverse();
- TabControl.TabPageCollection tabcoll = myTabControlZ.TabPages;
-
- foreach(TabPage tabpage in tabcoll)
- {
- myTabControlZ.SelectedTab = tabpage;
- myTabControlZ_SelectedIndexChanged(sender, e);
-
- if( ! tabpage.Text.Contains("Untitled"))
- {
- try
- {
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
- File.WriteAllText(FilenameToolStripLabel.Text, "");
- StreamWriter strwriter = System.IO.File.AppendText(FilenameToolStripLabel.Text);
- strwriter.Write(_myRichTextBox.richTextBox1.Text);
- strwriter.Close();
- strwriter.Dispose();
- }
- catch { }
- }
- }
-
- System.Windows.Forms.TabControl.TabPageCollection tabcollection = myTabControlZ.TabPages;
- foreach (TabPage tabpage in tabcollection)
- {
- String str = tabpage.Text;
- if (str.Contains("*")&& !str.Contains("Untitled"))
- {
- str = str.Remove(str.Length - 1);
- }
- tabpage.Text = str;
- }
- UpdateWindowsList_WindowMenu();
- }
- }
4. Close
If you have used any editor like Notepad++, it provides a function to close a file. Here, we will also create that function. This function is for nothing but to remove Tab from TabControl and remove node from treeView1 after saving a file. Here's the code to close a document. Download the source code to view "Close All" function code.
- private void File_Close_MenuItem_Click(object sender, EventArgs e)
- {
- if (myTabControlZ.TabCount > 0)
- {
- TabPage tabpage = myTabControlZ.SelectedTab;
- if (tabpage.Text.Contains("*"))
- {
- DialogResult dg = MessageBox.Show("Do you want to save " + tabpage.Text + " file before close ?", "Save before Close ?", MessageBoxButtons.YesNo);
- if (dg == DialogResult.Yes)
- {
-
- File_Save_MenuItem_Click(sender, e);
-
- myTabControlZ.TabPages.Remove(tabpage);
-
-
- this.UpdateDocumentSelectorList();
-
- UpdateWindowsList_WindowMenu();
- myTabControlZ_SelectedIndexChanged(sender, e);
-
- LineToolStripLabel.Text = "Line";
- ColumnToolStripLabel.Text = "Col";
-
- if (myTabControlZ.TabCount == 0)
- {
- FilenameToolStripLabel.Text = "Advanced Notepad in C#";
- }
- }
- else
- {
-
- myTabControlZ.TabPages.Remove(tabpage);
-
- UpdateDocumentSelectorList();
-
- UpdateWindowsList_WindowMenu();
- myTabControlZ_SelectedIndexChanged(sender, e);
-
- LineToolStripLabel.Text = "Line";
- ColumnToolStripLabel.Text = "Col";
-
- if (myTabControlZ.TabCount == 0)
- {
- FilenameToolStripLabel.Text = "Advanced Notepad in C#";
- }
- }
- }
- else
- {
-
- myTabControlZ.TabPages.Remove(tabpage);
-
- RemoveFileNamesFromTreeView(tabpage.Text);
- UpdateDocumentSelectorList();
-
- UpdateWindowsList_WindowMenu();
- myTabControlZ_SelectedIndexChanged(sender, e);
-
- LineToolStripLabel.Text = "Line";
- ColumnToolStripLabel.Text = "Col";
-
- if (myTabControlZ.TabCount == 0)
- {
- FilenameToolStripLabel.Text = "Advanced Notepad in C#";
- }
- }
-
- if (myTabControlZ.SelectedIndex >= 0)
- {
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
- _myRichTextBox.richTextBox1.Select();
- }
-
- }
- else
- {
- FilenameToolStripLabel.Text = "Advanced Notepad in C#";
-
- LineToolStripLabel.Text = "Line";
- ColumnToolStripLabel.Text = "Col";
- }
- }
5. Form Closing
When the form is closing, we need to check whether you want to save opened files or not. First, get each tab from tabcontrol, check whether that tab text contains "*" or not. If yes, then show dialog otherwise remove that tab page from tab control. If the result from dialog box is yes, then call save function & remove that tab. If dialog result is "Cancel", then stop the procedure & get out from the loop (for-each).
- private void MainForm_Closing(object sender, FormClosingEventArgs e)
- {
- if (myTabControlZ.TabCount > 0)
- {
- TabControl.TabPageCollection tabcoll = myTabControlZ.TabPages;
- foreach (TabPage tabpage in tabcoll)
- {
- myTabControlZ.SelectedTab = tabpage;
- if (tabpage.Text.Contains("*"))
- {
- DialogResult dg = MessageBox.Show("Do you want to save file " + tabpage.Text + " before close ?", "Save or Not", MessageBoxButtons.YesNoCancel);
- if (dg == DialogResult.Yes)
- {
- File_Save_MenuItem_Click(sender, e);
- myTabControlZ.TabPages.Remove(tabpage);
- myTabControlZ_SelectedIndexChanged(sender, e);
- }
- else if (dg == DialogResult.Cancel)
- {
- e.Cancel = true;
- myTabControlZ.Select();
- break;
- }
- }
- else
- {
- myTabControlZ.TabPages.Remove(tabpage);
- myTabControlZ_SelectedIndexChanged(sender, e);
- }
- }
- }
- }
Full Screen Mode
To set your application to full screen mode do following actions,
- Set Visibility of MainForm to false.
- Set FormBorderStyle to None of MainForm.
- Set Visibility of MainForm to true.
That's it your application is in full screen mode. To go to normal mode, perform all the above steps only just FormBorderStyle to Sizable.
Here's the code.
- private void View_FullScreen_MenuItem_Click(object sender, EventArgs e)
- {
- if(View_FullScreen_MenuItem.Checked==false)
- {
- this.Visible = false;
- this.FormBorderStyle = FormBorderStyle.None;
- this.Visible = true;
-
- View_FullScreen_MenuItem.Checked = true;
- }
- else
- {
- this.Visible = false;
- this.FormBorderStyle = FormBorderStyle.Sizable;
- this.Visible = true;
-
- View_FullScreen_MenuItem.Checked =false ;
- }
- }
But, if you have a customized form, then you cannot directly go to full screen mode as above. As your FormBorderStyle is none. So you need to store the current location & size of the MainForm. To go to full screen mode set WindowState to Maximized & Normal to go to normal window.
But remember to go to normal mode, first you need to set old(exact) location & size to your form(the size which was before full screen),then set form to visible and then set WindowState to Normal.
Here's the code
- Size formsizeholder = new Size(new Point(500, 300));
- Point formloc = new Point(0, 0);
-
- private void View_FullScreen_MenuItem_Click(object sender, EventArgs e)
- {
- if(View_FullScreen_MenuItem.Checked==false)
- {
- this.Visible = false;
- TopPanel.Visible = false;
- this.WindowState = FormWindowState.Maximized;
- this.Visible = true;
-
- formsizeholder = this.Size;
- formloc = this.Location;
-
- View_FullScreen_MenuItem.Checked = true;
- }
- else
- {
- this.Visible = false;
- TopPanel.Visible =true;
- this.Location = formloc;
- this.Size = formsizeholder;
- this.Visible = true;
-
- this.WindowState = FormWindowState.Normal;
-
- View_FullScreen_MenuItem.Checked =false ;
- }
- }
TabControl ContextMenuStrip
See above image that provides functions to selected tabpage like Save, Close, Close All But This, Open File Folder etc. You can see this function in almost all advanced editors like Notepad++ or IDE's like Visual Studio. You just need to create context menu strip, adding menus to it and adding this menu strip to tabcontrol.
1. Close All But This : This function perfoms action like to remove all other tabs without removing selected or current tab.
Here's the code.
- private void myTabControl_CloseAllButThis_MenuItem_Click(object sender, EventArgs e)
- {
- String tabtext = myTabControlZ.SelectedTab.Text;
- if (myTabControlZ.TabCount > 1)
- {
- TabControl.TabPageCollection tabcoll = myTabControlZ.TabPages;
- foreach (TabPage tabpage in tabcoll)
- {
- myTabControlZ.SelectedTab = tabpage;
- if (myTabControlZ.SelectedTab.Text != tabtext)
- {
- File_Close_MenuItem_Click(sender, e);
- }
- }
- }
- else if (myTabControlZ.TabCount == 1)
- {
- File_Close_MenuItem_Click(sender, e);
- }
- }
2. Open File Folder : This function opens the folder where the file is saved. Here's the code.
- private void myTabControl_OpenFileFolder_MenuItem_Click(object sender, EventArgs e)
- {
- if(myTabControlZ.TabCount>0)
- {
- if( ! myTabControlZ.SelectedTab.Text.Contains("Untitled"))
- {
- if(FilenameToolStripLabel.Text.Contains("\\"))
- {
- TabPage tabpage = myTabControlZ.SelectedTab;
- String tabtext = tabpage.Text;
- if(tabtext.Contains("*"))
- {
- tabtext = tabtext.Remove(tabtext.Length - 1);
- }
- String fname = FilenameToolStripLabel.Text;
- String filename=fname.Remove(fname.Length-(tabtext.Length+1));
- Process.Start(filename);
- }
- }
- }
- }
File Association
Visual Studio allows you to add specific file extensions to the application. To access this property the .NET Framework version must be greater than or equal to 3.5. For adding file extensions, go to your Project Properties. Select Publish tab. Click on Options button. Once "Publish Options" Dialog box appears then select "File Associations" item and add your file extension with icon here.
So how to open a file in the application when double clicking on file ?
Well it's so much simpler when you double click on a file or right click on a file and select a program, that file name is passed as an argument to the application. So you just have to open this file in the application in the main function of the program. First define the function in the MainForm that opens a file and takes a filename as an argument. You must define this function modifier to public. Code is same as open file as define above in Open function just adding parameter to it. I am using OpenAssociatedFiles_WhenApplicationStarts(String[] files) function to open files.
You have to call this function in the main function of program which is in Programs.cs file. First check that the arguments are not null, if it is null then call Application.Run(new MainForm()); otherwise create object of MainForm and call the defined function that open these files (OpenAssociatedFiles_WhenApplicationStarts(args);).
Here's the main code of my application or Program.cs file code.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Windows.Forms;
- using System.IO;
- namespace AdvancedNotepad_CSharp
- {
- static class Program
- {
-
-
-
- [STAThread]
- static void Main(String[] args)
- {
- if (args != null && args.Length > 0)
- {
- String[] files = args;
-
- MainForm mf = new MainForm();
- mf.IsArgumentNull = false;
- mf.OpenAssociatedFiles_WhenApplicationStarts(files);
- Application.EnableVisualStyles();
- Application.Run(mf);
- }
- else
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
- }
- }
- }
- }
Tab Changed
When you change the tab of tabcontrol then the status strip label value must be changed like full filename. To handle this situation,you need to add SelectedIndexChanged event to tabcontrol. Here's the code that set filename to status strip when tab index is changed.
- private void myTabControlZ_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (myTabControlZ.TabCount > 0)
- {
- TabPage tabpage = myTabControlZ.SelectedTab;
- if (tabpage.Text.Contains("Untitled"))
- {
- FilenameToolStripLabel.Text = tabpage.Text;
- this.Text = "Advanced Notepad in C# [ "+tabpage.Text+" ]";
- UpdateWindowsList_WindowMenu();
- }
- else
- {
- foreach (String filename in OpenedFilesList)
- {
- if (tabpage != null)
- {
- String str = filename.Substring(filename.LastIndexOf("\\") + 1);
- if (tabpage.Text.Contains("*"))
- {
- String str2 = tabpage.Text.Remove(tabpage.Text.Length - 1);
- if (str == str2)
- {
- FilenameToolStripLabel.Text = filename;
- this.Text = "Advanced Notepad in C# [ " + tabpage.Text + " ]";
- }
- }
-
- else
- {
- if (str == tabpage.Text)
- {
- FilenameToolStripLabel.Text = filename;
- this.Text = "Advanced Notepad in C# [ " + tabpage.Text + " ]";
- }
- }
- }
- }
-
- UpdateWindowsList_WindowMenu();
- }
- }
- else
- {
- FilenameToolStripLabel.Text = "Advanced Notepad in C#";
- this.Text = "Advanced Notepad in C#";
- UpdateWindowsList_WindowMenu();
- }
- }
Select Tab when Mouse Click on Tree Node
As you know, every editor has a document selector where a user can click on list of document and that document is activated. In Tabbed document,when you double click on tree node then same text of tree node is searched in tabcontrol,if that text is matched then that tab is selected.
Here's the code to select the tab.
- private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
- {
- String str = treeView1.SelectedNode.ToString();
- String st = str.Substring(str.LastIndexOf(":") + 2);
- int treenode_length = st.Length;
- int tab_count = myTabControlZ.TabCount;
-
- System.Windows.Forms.TabControl.TabPageCollection tb = myTabControlZ.TabPages;
- foreach (TabPage tabpage in tb)
- {
- String tabstr = tabpage.Text;
- int tab_length = tabstr.Length;
- if (tabstr.Contains(st))
- {
- myTabControlZ.SelectedTab = tabpage;
- }
- }
-
- if (myTabControlZ.SelectedIndex >= 0)
- {
- var _myRichTextBox = (MyRichTextBox)myTabControlZ.TabPages[myTabControlZ.SelectedIndex].Controls[0];
- _myRichTextBox.richTextBox1.Select();
- }
-
- this.UpdateWindowsList_WindowMenu();
- }
When you move the mouse on the menu item, it shows information about that menu item actions in the status strip label. As you know this can be achieved by adding MouseEnter & MouseLeave events to the menu item. But if you have many items then it could take so much time to type code for each menu item. So here's the solution. First create the function that take parameter of a class ToolStripMenuItem (ChangeTextOfReadyLabel(ToolStripMenuItem menuitem)). Add MouseEnter & MouseLeave events to the object of ToolStripMenuItem. In MouseEnter events function get text of selected menu item.
e.g.:
Object b = (ToolStripMenuItem)sender;
String s = b.ToString().Trim();
Compare String s with your menu item text like "File","New","Open" etc. and set label text to its information. In MouseLeave events function set label text to its default text. Now create another function,and call created above function "ChangeTextOfReadyLabel()" and pass object of menu item. And call this created function in Form_Load event. Call following function UpdateReadyLabel() in Form_Load event function.
Here's the code
- public void ChangeTextOfReadyLabel(ToolStripMenuItem menuitem)
- {
- menuitem.MouseEnter += new EventHandler(this.menuitem_MouseEnter);
- menuitem.MouseLeave += new EventHandler(this.menuitem_MouseLeave);
- }
- private void menuitem_MouseEnter(object sender,EventArgs e)
- {
- Object b = (ToolStripMenuItem)sender;
- String s = b.ToString().Trim();
- switch(s)
- {
- case "File": AboutLabel.Text = "Create New,Open,Save,Close and Print Documents";
- break;
- case "New": AboutLabel.Text = "Create New document";
- break;
- case "Open": AboutLabel.Text = "Open New Document";
- break;
- case "Save": AboutLabel.Text = "Save Current Document";
- break;
- case "Save As": AboutLabel.Text = "Save As Current Document";
- break;
- case "Save All": AboutLabel.Text = "Save All opened documents";
- break;
- case "Close": AboutLabel.Text = "Close Current Document";
- break;
- case "Close All": AboutLabel.Text = "Close All Opened Documents";
- break;
- case "Open In System Editor": AboutLabel.Text = "Open current document in its system editor";
- break;
- case "Print": AboutLabel.Text = "Print Current Document";
- break;
- case "Print Preview": AboutLabel.Text = "Print Preview Current Document";
- break;
- case "Exit": AboutLabel.Text = "Exit from Application";
- break;
- }
- }
- private void menuitem_MouseLeave(object sender, EventArgs e)
- {
- AboutLabel.Text = "Ready";
- }
-
- public void UpdateReadyLabel()
- {
- ChangeTextOfReadyLabel(File_MenuItem);
- ChangeTextOfReadyLabel(File_New_MenuItem);
- ChangeTextOfReadyLabel(File_Open_MenuItem);
- ChangeTextOfReadyLabel(File_Save_MenuItem);
- ChangeTextOfReadyLabel(File_SaveAs_MenuItem);
- ChangeTextOfReadyLabel(File_SaveAll_MenuItem);
- ChangeTextOfReadyLabel(File_Close_MenuItem);
- ChangeTextOfReadyLabel(File_CloseAll_MenuItem);
- ChangeTextOfReadyLabel(File_OpenInSystemEditor_MenuItem);
- ChangeTextOfReadyLabel(File_Print_MenuItem);
- ChangeTextOfReadyLabel(File_PrintPreview_MenuItem);
- ChangeTextOfReadyLabel(File_Exit_MenuItem);
- }
Download the source code to view complete application. You can use syntax highlighting editors instead of RichTextBox. you can use IC SharpCode AvalotEdit or TextEditorControl.
I used simple RichTextBox only for showing about advanced operations like Open, Save All, Close etc.
Read more articles on C#: