Advanced Notepad for the Beginner

I read an article by Nikhil Kumar regarding his Notepad 2009, the following is my version of how to create a notepad program with cleaner more advanced programming techniques, and this example will show you how to access the methods, events and properties of other forms of the project with very little code.

The task was to write a Multiple Document interface to open as many documents limited only by the amount of memory on the computer system the application was running on.

The first thing that needed to be done was to decide who did what, that is should the main form do all of the work or just some of the work that is needed to open windows, set properties etc. etc.

I decided that since it was an MDI application I would get the parent form (frmMain class) to do most of the work in relation to setting properties of all it's child forms (frmDocument class) and let the child handle the more relative functions, methods and events.

frmMain (The Parent form)

This form contains two ToolStrip containers with all the menu options and buttons needed to set the properties of the child forms, options for New, Open, Save, Copy, Cut, Paste, Alignment and many more.

But how do you use one set of ToolStrip options objects to do this? he key is to declare a public variable array of type frmDocument

public frmDocument[] docForms = new frmDocument[0];

Notice I have declared the array with 0 (zero) elements in length, you will see why later.

I have also declared public variables that can be accessed by child forms when needed.

public int index;
public int form_index;
public int selectedForm;
private int indent;
private int indentSize;

When the application is launched, the frmMain_Load event creates a new form by calling the createForm() function.

private int createForm()
{
    Array.Resize(ref docForms, docForms.Length + 1); //resize the forms array by 1
    form_index = docForms.Length - 1;     //this is the index into the forms array
    docForms[form_index] = new frmDocument();          //instantiate a new document form
    docForms[form_index].MdiParent = this;         //set form as child of main MDI form
    docForms[form_index].Text = "New Document";       //set form caption
    docForms[form_index].thisIndex = form_index;        //set thisIndex to the index into forms array
    docForms[form_index].Show();  //now show the form...
    return (form_index);
}

It also sets the default font size, style and indent size. 

Before going any further, let's look at the document form (frmDocument) to see what it has.

Firstly I have declared a public RichTextBox doc, public Panel findP in the class declaration before the constructor these, along with other publically declared variables can be accessed from any form that has access to the docForms array on frmMain, I have also declared an frmMain f.

Ok, so why have I done this? What I do in the frmDocument_Load event will interest you in that we now point to the RichTextBox placed on the form by declaring that doc = te (the name I called the RichTextBox) and findP = p (the name I gave the Panel) I also do the following,

f = (frmMain)ParentForm;//this allows access to parent forms methods, events and public variables

This now allows us to access ALL the properties, events and methods of te through doc and p through findP from any form that has access to the docForms array declared in frmMain, for example

If we declared a variable public frmDocument myDocument = new frmDocument() we could access the properties of te by a statement like this

myDocument.doc.Text = "This is my text document example"; or
myDocument.doc.Font = new Font( ... );

How easy is this? 

Ok, let's continue with frmMain.

When we want a new form with an empty text box we click the New document button on the ToolStrip, what does this actually do.

It simply creates a new form by calling the createForm() function and sets the default font and style for the form but remember, each new form created is added to the docForms array.

What happens when we open a document? Much the same as a New document except that on open file dialog is shown inviting you to open any text document.

If you click on OK, the document is loaded into the text box of the new form created by the createForm() function, but, if you cancel, the new form is discarded.

Ok, we have a number of forms with documents open, how does the ToolStrip objects know which form to work on, easy, the frmDocument_Activated function tells frmMain that it is the current form eg,

//let parent form know that this form identified by thisIndex is the active form
f.selectedForm = thisIndex;
//let the parent form adjust font size combo box with size of acctive forms document
//with more work can be made to show font size of selected text.
f.setFontCombo(fontSize);

Now that frmMain knows which the current form by its index is, we can access the forms controls, properties, events and methods by the use of the docForms array eg.

docForms[formIndex].doc.Text = "Whichever document you want to work with";

Ok, so what happens when I close a form? A number of things happen, to begin with, if there were text changes made the forms dirty property was set to true and if true, the frmDocument_FormClosing event kicks in and checks if a save dialog should be triggered.

This checks two conditions the first is, is the file property of the form null or empty, if it is not, it simply saves the file to the path and file name referred to the file property of the form, however, if file is empty, a save file dialog is opened giving you the option to save the file in the path and file name specified.

After this, the frmDocument_FormClosed event is triggered, this informs frmMain that the form is no longer available and to do some housework to ensure that form indexes are valid, this is done by comparing the index of the closed form with the indexes of the docForms array by calling frmMains removeForm(index) function eg.

//closed forms need to be removed from forms array
f.removeForm(thisIndex);

public void removeForm(int index)
{
          frmDocument[] f = new frmDocument[0]; //temporary forms array
          for(int i = 0; i < docForms.Length; i++)
          {
                   if(i != index )  //if its not the form index
                   {
                             Array.Resize(ref f, f.Length +1); //add form to temp forms array
                             f[f.Length -1] = docForms[i];       
                             f[f.Length-1].thisIndex = f.Length-1;//set form index to the new form index into the forms array
                   }
          }
          docForms = f; //assign f to docForms
}

Remember I said that frmMain would do most of the work, here is a case where frmMain gets frmDocument to perform the task of opening a document in the active form, if it fails, the newly created form is closed and the array is resized to one less than the length of the array removing the reference to the new form that was closed.

private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
          index = createForm();
          if(!docForms[index].openFile())
          {
                   docForms[index].Close();  //open file was cancelled, close form
                   Array.Resize(ref docForms, docForms.Length-1); //remove last form array   
          }
}

As you can see here and through the project files there are simple techniques to make the task of writing applications simpler than what I have seen in this forum.

It is no good just being able to write programs, anyone can do that, to write good programs you need to have some imagination and be able to identify the needs of clients with a vision to produce the best solution for the clients specific problem with an emphasis on user friendliness, if you can do this, then you are a good programmer.