Page 1 of 1

NotePad (RexPad) Tutorial: Step by Step

#1 RexGrammer   User is offline

  • Coding Dynamo
  • member icon

Reputation: 183
  • View blog
  • Posts: 785
  • Joined: 27-October 11

Posted 13 December 2011 - 10:48 AM


NotePad Tutorial (RexPad)

NotePad Tutorial (RexPad)

In this tutorial I will try to guide you through the process of creating a NotePad application (We will try to implement a lot of MS Notepad features)

The definition for Notepad (WIKI)

Some common software notepads:
MS Notepad (WIKI)
Notepad++ (WIKI)

So I want to think about the project before we do any code or design

What features do we want:

1. We need to have a nice menu that contains: File, Edit, Format, View and Help menu strips
2. In the file menu strip the buttons we want are: New, Open, Save, Save As, Page Setup, Print Preview, Print and Exit
3. In the edit menu strip the buttons that should be included are: Undo, Cut, Copy, Paste, Delete, Find, Find Next, Replace, Go To, Select All and Time/Date
4. The buttons in the format menu strip should be: Word Wrap and Font
5. The view menu strip should contain only the Status Bar button
6. In the Help menu strip there should be a View Help and a About button

(NOTE: It's understood that we need to implement features for all buttons)

7. We want a nice big multiline textbox to edit text
8. We want to show the scroll bars in the textbox in accordance to the features currently selected

So that wraps up the story on our features...

Since this is not exactly the smallest of projects I will explain the implementation of these features on the fly...

A note before proceeding: I renamed the form from the default name 'Form1' to 'MainForm'

First we need a good design that we will copy from MS Notepad! :D

You have notepad you can copy it yourself but if you're too lazy, you can see the pics of my gui bellow

Add a menustrip to the form and add 5 menuItems: File, Open, Format, View, Help

Next add the menu buttons to the menu items accordingly to the pics bellow:


And of course for the main text editing body we will use a text box (NOT a richTextBox, because it's not needed, maybe you can upgrade the application and make use of the richTextBox? :))

Let's add the textbox:

1. So add a textBox control to the form (I named it mainTextBox, you can too if you like) Duh!

2. Now change the dock property of the textBox to 'Fill' (Click in the center)
(This will make the textBox fill the form, the great thing about it is it will resize if you add a status strip so that they all fit the form, nice huh? )

Now to tackle some actual code...

We'll need a global variable that holds the current file path and a variable to hold the previous file (So that we may compare them when we need to detect if changes were made)

So lets declare those variables

        private string _filePath;
        private string _oldFile;

Now let's add some functionality to the program.

Format Features

Let's tackle the font first

Font Feature

So we need to change the font of the text within the text box, we will do that by showing a font dialog and then seting the text box font property to the font selected in the dialog...

First add a font dialog to the form (drag a fontDialog from the toolbox to the form)
Then rename it from fontDialog1 to fontDialog (since it will be the only one that will be used)

Then we need to show the font dialog

NOTE: All dialogs return a dialog result when shown

We need to catch the result and check if the user clicked OK so we will do it like this

Add this to the fontToolStripMenuItem_Click event handler

            DialogResult result = fontDialog.ShowDialog();
            if (result == DialogResult.OK)
                mainTextBox.Font = fontDialog.Font;

You can compile, build and run the program (It shouldn't have any error)

The project is now one tiny, tiny, tiny step closer to being finished

Word Wrap Feature

Word Wrap means it will make the text fit into the text box, it wont go beyond the text box frame

I found out what word wrap actually meant while I was making this... :D

You should now change the check on click property of the word wrap menu item to true...

Now we need to make the text box wrap the words in it and display the horizontal scroll bar in accordance to the feature state (on or off)

I created a method for this since it will be called from two places (later in the mainForm_Load event and here), and double code is a maintenance nightmare!

So let's create a private void method
private void TextBoxModeChange()

Now the text box control actually has a word wrap property we can change

mainTextBox.WordWrap = wordWrapToolStripMenuItem.Checked;

In the code above we set the text box word wrap feature on or off according to the checked property of the word wrap toolstrip menu item, and we set the checkonclick feature of the wordWrapToolStripMenuItem to true so then it will change when clicked

We also need to make changes to the textBox scroll bars (if word wrap is off show the horizontal & vertical scroll bar if it's off then just the vertical scroll bar)

Add this code to our method

mainTextBox.ScrollBars = wordWrapToolStripMenuItem.Checked ? ScrollBars.Vertical : ScrollBars.Both;

So if you're wondering whats the ? : , it's a inline if statement

It is equal to

if (wordWrapToolStripMenuItem.Checked)
   mainTextBox.ScrollBars = ScrollBars.Vertical;
   mainTextBox.ScrollBars = ScrollBars.Both;

So now add the call to that method from the wordWrapToolStripMenuItem_Click and the MainForm_Load event handler


This wraps up the story on both the word wrap feature an the format features...

View Features

The only feature here is the status bar so let's do that

Status Bar Feature

If you saw what is a status bar in MS Notepad you will see it shows what line and column are you on... We'll do just that...

Add the status strip control from the toolbox to the form (Drag it from the toolbox to the form)

When the status bar shows we need to move and resize the textbox to accommodate for the space needed for the status bar. NOT! The dock property we set to fill at the start does that for us (Neat, huh?)

So what need to be done when you click the button?

Well if the status bar is visible the hide it and uncheck the menu item, else show it and check the menu item

Make a method that returns void and it's private
private void StatusBarChange(){}

Add the following code:
        private void StatusBarChange()
            if (statusStrip1.Visible)
                statusBarToolStripMenuItem.Checked = false;
                statusStrip1.Visible = false;
                statusBarToolStripMenuItem.Checked = true;
                statusStrip1.Visible = true;

Now call that method from the status bar menu item click event handler...

Let's now tackle the problem of showing the correct text in the status bar...

Again create a new method to do this:

private void StatusBarUpdate(){}

Now let's think how are we going to do this?

The text box provides the following methods (amongst others):


So we are going to get the current line like this:

int statusBarLine = mainTextBox.GetLineFromCharIndex(mainTextBox.GetFirstCharIndexOfCurrentLine());

This gets the line number from the first char index of the current line, that is get the current line

We'll get the column number with the following code:
int statusBarColumn = mainTextBox.Selectionstart - mainTextBox.GetFirstCharIndexOfCurrentLine();

So what this does is subtracts the char index of the first char in the current line from the current cursor position (You get the column)

And now we only need to update the status bar text:
toolStripStatusLabel1.Text = "Ln " + statusBarLine.ToString() + ", Col " + statusBarColumn.ToString();

Now we'll create a custom event handler called mainTextBox_Changed, and call the previously created method

We can do this like this
 private void mainTextBox_Changed (object sender, EventArgs e)

Now we need to link the events to the event handler...

Look at the pic for info:


This way we can link multiple events to one event handler...

I linked the Click, KeyPress and TextChanged events of the mainTextBox to our event handler... (If you see some more events that should be linked please do so)

Help Features

I will only add the about box feature, I will leave it up to you to implement the Help feature (If you want to)

About RexPad Feature

Now we need to add a about box to the project, luckily the .NET Framework has a template for this...

Add the AboutBox template to the project:

1. Right-Click the project in the Solution Explorer
2. Click Add->New Item->About Box

Now we need to show the about box...

            AboutRexPad aboutBox = new AboutRexPad();

Declare and initialize a new about form and show it as a dialog...

NOTE: The about box template already gets all of the info needed from the assembly no coding necessary...

Edit Features

Undo Feature

The text box control has a nice method that's called .Undo(), that does exactly what we want.

So check if the textBox can undo with the mainTextBox.CanUndo property and if it can undo then call that method in the undo menu strip item click event handler...

if (mainTextBox.CanUndo)

Cut Feature

Again the text box control jumps in to help us with this feature

The text box has a .Cut() method and a .SelectionLength property...

Add this code to the cutMenuStripItem_Click event handler...
If the user has selected something, then cut it:

if (mainTextBox.SelectionLength != 0)

Copy Feature

The text box control saves our day, again...

It provides a .Copy() method...

So in the cutMenuStripItem_Click event handler:

Check if the user has selected something and if he has then copy it to the clipboard:

if (mainTextBox.SelectionLength != 0)

Paste Feature

This is the only feature we will need to use out head (at least a little)

So we need to check if there is some text in the clipboard, if there is paste it to the textbox and position the cursor at the end of the text...

So this goes in the pasteMenuStripItem_Click event handler

            if (Clipboard.GetText() != "")
                mainTextBox.Selectionstart = mainTextBox.TextLength;
                mainTextBox.SelectionLength = 0;

So to recap what we have done: Using the .GetText() method of the clipboard we got the text contents of the clipboard and we are checking if it's null (that is if it's not empty). If it's not empty then paste the contents to the text box, and then position the cursor at the end of the text (since by default it positions at the start of the textbox)...

Select All Feature

We'll return to the features we skipped in a moment (I like to do the easy things first :))

The select all is a easy one (since the text box provides a .SelectAll() method:


Otherwise (if there wasn't that method) we would need to set the .Selectionstart property of the text box to 0, and set the .SelectionLength to the length of the text box text!

Time/Date Feature

This should also be easy:

Just add this to the timeDateToolStripMenuItem_Click event handler
mainTextBox.Text += DateTime.Now;

Find Feature

Now comes the hard part...

Create a new form (I called it 'Find'):

1. Right-Click the project name in the solution explorer
2. Click Add->Windows Form
3. Name it Find (If you want) and click OK!

So now it needs some design:

I did it like this:

Posted Image

So now I created a class to hold some variables for finding text/replacing text...

1. Right-Click the project name in the solution explorer
2. Click Add->Class
3. Name it Functions (If you want) and click OK!

Make that class static since we need only one instance of it!

Add a static auto-property to the class we added:
public static string TextToFind { get; set; }

The compiler translates this to something similair to this:
private static string _textToFind;
public static string TextToFind 
get {return _textToFind;} 
set {_textToFind = value;} 

I won't explain what static classes are here, you can check about that here:
Static Classes and Static Class Members (C# Programming Guide) on MSDN!

Let's code the cancel button (Remember that I like to start with the simplest parts:)):

On the Find Next button you should set the TextToFind property of the Function class to the text you entered in the text box and the close the form!

Functions.TextToFind = textBox1.Text;

In the Load event of this form you should set the text box text to the last search if there is one (a feature so that the program looks more polished):

if (Functions.TextToFind != "")
                textBox1.Text = Functions.TextToFind;

Now for the mainForm part of the function:

When you click the find button of the menu strip you should declare and initialize a new find form and show it...

Find findForm = new Find();

Now let's make a find method:

We'll make the method private and the parameters should be the text to find and a referenced find form:

private void Find(string textToFind, ref Find findForm){}

The body of the method should check if there is in the textBox the text we passed as a parameter, and show a message box that tells the user that there hasn't been a match! Then show the referenced find form...

We can do that with the .IndexOf() method of the text of the text box.

NOTE: The method returns -1 if there isn't a match (since the index of -1 doesn't actually exist in any textbox)

If there is that text then select that text in the textbox

NOTE: To select the text you need to set the selection start to the index of the searched word, then set the selection length to the length of the word that you want to find

I did it like this:

Find Next Feature

This is far easier than the find feature (son don't worry...)

We need to declare and initialize a new form that will be referenced in the find method and then call that method passing the text in the Functions.TextToFind property as the textToFind parameter

You can do it like this:

Find findForm = new Find();
Find(Functions.TextToFind, ref findForm);

Replace Feature

Before we start add a ReplacementText auto-property to the functions class

Again we need to make a new form for this:

I designed it like this:

Posted Image

NOTE: My original idea was to use one form for find & replace, but since MS Notepad had two, and I wanted to copy it to the letter I created two separate forms...

So we need to make two auto-properties to see if the user has clicked FindNext or ReplaceAll

public bool FindNextClicked { get; private set; };
public bool ReplaceAllClicked { get; private set; };

NOTE: since the property is public that means that by default that both get and set are public, but you can specify a different access modifier to a method
NOTE: You can set only one method to a access modifier different to the property modifier

When the user clicks FindNext the program should, if the user has entered some text in the text box, set the FindNextClicked to true and ReplaceAllClicked to false, and pass the text entered to the functions class.

I did it like this:

            if (textBox1.Text != null)
                FindNextClicked = true;
                ReplaceAllClicked = false;
                Functions.TextToFind = textBox1.Text;

When the user clicks the replace all button the program should check if there is any text in both textBoxes and then set the FindNextClicked to false and ReplaceAllClicked to true! Also set the Function.TextToFind property to the entered text and Function.ReplacementText to the entered text!

You can do it like this:
if (findTextBox.Text != null && replaceTextBox.Text != null)
                ReplaceAllClicked = true;
                FindNextClicked = false;
                Functions.TextToFind = findTextBox.Text;
                Functions.ReplacementText = replaceTextBox.Text;

Also we should add a functionality to the load event to the form:

If there is some text in the functionality TextToFind or ReplacementText properties set the textBox's text to the properties...

You could do it like this:

 if (Functions.TextToFind != null)
                findTextBox.Text = Functions.TextToFind;
if (Functions.ReplacementText != null)
                replaceTextBox.Text = Functions.ReplacementText;

Now for the part in the main form:

In the replaceAllMenuItem_Click event handler we need to add the following functionality:

Declare and initialize a new replace form and then show it as a dialog:

Replace replaceForm = new Replace();

And then if the user has clicked find next, declare and initialize a new find form and call the Find method, passing the Function.TextToFind and the findForm as the parameters:

if (replaceForm.FindNextClicked)
                Find findForm = new Find();
                Find(Functions.TextToFind, ref findForm);

If not, BUT the user has clicked replace all, then we need to call a method, that we'll make now...

Let's make it private and the parameters should be the text to replace and the replacement text...
private void ReplaceAll(string textToReplace, string replacementText){}

Before proceeding we need to add a using statement at the start of the project...

using System.Text.RegularExpressions;

Now we can finish our method:

First we need a string that will hold the original text of the text box (in which the words will be replaced) and a regex to change the words...

Then we should call the .Replace() method of the regex to replace the words...

If the replaced text is the same as the original text then tell the user that there was nothing replaced because there were no words to replace, else tell the user

The main body of the method could look like this:
            Regex regex = new Regex(textToReplace);
            string finishText = regex.Replace(mainTextBox.Text, replacementText);
            if (mainTextBox.Text == finishText)
                MessageBox.Show("Nothing was replaced, because there were no words to replace!");
                mainTextBox.Text = finishText;
                MessageBox.Show("'" + textToReplace + "' was replaced by '" + replacementText + "'");

Now to finish the logic of the replaceAllMenuStripItem_Click event handler:

I added the rest like this:
if (replaceForm.FindNextClicked)
                Find findForm = new Find();
                Find(Functions.TextToFind, ref findForm);
            else if (replaceForm.ReplaceAllClicked)
                ReplaceAll(Functions.TextToFind, Functions.ReplacementText);

GoTo Feature

Now let's design the form:

Posted Image

Add a public auto-property of type bool called GoToClicked...
public bool GoToClicked { get; private set; }

So the close button (that should also set the GoToClicked to false):
GoToClicked = false;

Now on the lineTextBox_KeyPress:

You need to set the KeyPreview property of the form to true...

We should limit the user to entering only numbers:

This is just a simple snippet that does just that
int isNumber = 0;
e.Handled = !int.TryParse(e.KeyChar.ToString(), out isNumber);

We'll now add some code to the load event:

We'll set the text box text to the functions property! :)
lineTextBox.Text = Functions.GoToLineNumber.ToString();

Before we tackle the goToButton code we'll return to the main form's goToMenuStripItem_Click:

We need to add a MaxNumberOfLines auto-property to the functions class:

public static int MaxNumberOfLines { get; set; }

Next in the go to menu strip item click event handler we set it to the mainTextBox.Lines.Count();

Then we declare a new goToForm and show it:

Functions.MaxNumberOfLines = mainTextBox.Lines.Count();
GoTo goToForm = new GoTo();

Now let's return to the goToButton click event handler of the Go To from...

In it we need to set the functions go to line number to the parsed int value of the lineTextBox

NOTE: We don't need to check if it's a int since we limited the user to only enter numerical values...

If the GoToLineNumber is greater than the MaxNumberOfLines them show a message to the user, else pass that value to the GoToLineNumber, set the GoTo indicator to true property and close the form

I did it like this:

            if (int.Parse(lineTextBox.Text) > Functions.MaxNumberOfLines)
                MessageBox.Show("The line number is beyond the total number of lines");
                GoToClicked = true;
                Functions.GoToLineNumber = int.Parse(lineTextBox.Text);

Now let's return to the main form...

Let's continue the goToMenuStripItem_Click event handler...

If the user clicked 'Go To' then go to the line specified...
if (goToForm.GoToClicked)
                mainTextBox.Selectionstart = mainTextBox.GetFirstCharIndexFromLine(Functions.GoToLineNumber - 1);
                mainTextBox.SelectionLength = 0;

Extra Feature

When the user clicks the edit menu it should enable only the buttons that can actually do something

So if the mainTextBox can't undo then the undo button should be disabled, also if there isn't anything in the clipboard the paste button should be disabled, and if nothing is selected, then neither copy nor paste should be enabled

You could do it like this:

            if (mainTextBox.CanUndo == false)
                undoToolStripMenuItem.Enabled = false;
            if (Clipboard.GetText() != "")
                pasteToolStripMenuItem.Enabled = false;
            if (mainTextBox.SelectionLength == 0)
                copyToolStripMenuItem.Enabled = false;
                cutToolStripMenuItem.Enabled = false;

File Features

Exit Features

Haven't I said that I always do the easiest parts first? :)

:) Guess what goes now?


Page Setup Features

Now comes the set of features involving printing...

Now add a print document to the form:

1. Drag the print document from the toolbox to the form

Add the page setup dialog to the project

1. Drag the page setup dialog from the toolbox to the form

So we first need to set the .Document property of our page setup dialog to our print document

pageSetupDialog1.Document = printDocument1;

Now open the dialog and 'catch' the result...

DialogResult result = pageSetupDialog1.ShowDialog();

So now we want to set the document settings to the user selected if the user clicked 'OK':

if (result == DialogResult.OK)
                printDocument1.DefaultPageSettings = pageSetupDialog1.PageSettings;
                printDocument1.PrinterSettings = pageSetupDialog1.PrinterSettings;

Print Preview Features

Add a print preview dialog to the project:

1.Drag the print preview dialog from the toolbox to the form

Set the .Document property of the print preview dialog to our print document

printPreviewDialog.Document = printDocument;

Then show the dialog and 'catch' the result:

DialogResult result = printPreviewDialog.ShowDialog();

And if the user clicked 'OK' then print the document:

 if (result == DialogResult.OK)

Print Features

We need to sync the dialog document and our document:

printDialog.Document = printDocument;

Show the dialog and 'catch' the result:
DialogResult result = printDialog.ShowDialog();

And if the user clicked 'OK' then print the document:
if (result == DialogResult.OK)

Now we need to poke around with the windows designer code... (Don't run off now, it's nothing scary :) )

We need to create a custom event...

Now I'm not going to explain what are custom events

There is a GREAT tutorial on custom events here on DIC:
Quick and easy custom events

So pick a place in the designer generated code and add this code:
 this.printdocument.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.printDocument_PrintPage);

What this does is creates an event that triggers when you print the page

Now we need to create a event handler for that event:

Back in the main form code you should add this:

 private void printDocument_PrintPage(Object sender, System.Drawing.Printing.PrintPageEventArgs e)

For the body of the event handler we should draw the text in the textbox to the document, but first we need graphics to draw something, luckily the printpage event args already has one:

Graphics g = e.Graphics;

Now draw the text with the font in black:

            g.DrawString(mainTextBox.Text, mainTextBox.Font, Brushes.Black, 0, 0);

New Features

So now we need to reset the file path and the textBox text (that's the easy pary), but more importantly we need to prompt the user to save the changes if he has done anything...

So create a new method called SaveChanges:

private void SaveChanges()

So the method should check if the old file is not equal to the text box text:
 if (_oldFile != mainTextBox.Text)

And then if the file path is null:

if (_filePath != null)

So now let's show a message to the user and catch the input:

DialogResult result = MessageBox.Show("Do you want to save the changes to " + _filePath, "Saving Changes",

And if the user clicked yes save the file

if (result == DialogResult.Yes)

You see we invoked a non-existing method Save now we're going to create it too:

It should accept a string indicating the file to save as a parameter:
private void Save(string fileToSave)

Now to check if the parameter inputed isn't empty:

if (!string.IsNullOrWhiteSpace(fileToSave))

And then save the file to the file path specified:

using (var myWriter = new StreamWriter(fileToSave))

OK we done the new feature!

Open Features

Just call a Open method that we'll make now:


Now let's code that method:

private void Open()

Now call the method we created just a moment ago the SaveChanges()

Now add a open file dialog to the project:

1. Drag the openFile dialog from the toolbox to the form!

Now show the dialog and 'catch' the input:

DialogResult result = openFileDialog.ShowDialog();

And if the user clicked ok:

 if (result == DialogResult.OK)

Now check if the user selected a valid file:
 if (!string.IsNullOrWhiteSpace(openFileDialog.FileName))

Now set the file path to the one selected:

_filePath = openFileDialog.FileName;

We now need to set the text box text the _oldFile (the string that holds the original document) to the full text of the file

using (var myReader = new StreamReader(_filePath))
                        mainTextBox.Text = _oldFile = myReader.ReadToEnd();

We've done the open method!

Save Features

I think that this is the hardest feature of the file feature set...

Prepare! :)

Now check if the file path is empty and if not save the file:

if (!string.IsNullOrWhiteSpace(_filePath))

else if it's empty:


Now add a save file dialog to the project:

1. Drag a saveFileDialog from the toolbox to the form

Show it and catch the input:

 DialogResult result = saveFileDialog.ShowDialog();

And if the user clicked ok:

 if (result == DialogResult.OK)

Set the file path to the one specified and save the file:

filePath = saveFileDialog.FileName;

Save As Features

I guess your mind is fulled with this: "YES THE LAST ONE!!!"

It's always nice to see a final product that you created!

So show the save file dialog and 'catch' the result:

DialogResult result = saveFileDialog.ShowDialog();

Check if the user clicked 'OK' and if he has:

if (result == DialogResult.OK)

Set the file path to the one specified and then save the file!

 _filePath = saveFileDialog.FileName;

Now step back

and see what you created:

Isn't it wonderful?

Now if you have followed through the whole tutorial you have made a step forward into C#. Congrats!

Now there is still much room for improvement, just by writing this tutorial I have seen and fixed many of my code errors!

An idea is to add syntax highlight!

So check my GitHub Repo for the bleeding edge version of the program!

Also you can upload the project as a attachment:
Attached File (899.45K)
Number of downloads: 3122

Is This A Good Question/Topic? 5
  • +

Replies To: NotePad (RexPad) Tutorial: Step by Step

#2 chrisdonals   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 03-May 09

Posted 27 May 2012 - 11:23 PM

I did this tutorial today. Thanks. I need the practice, and the assistance.
Was This Post Helpful? 0
  • +
  • -

#3 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7053
  • View blog
  • Posts: 23,974
  • Joined: 05-May 12

Posted 29 May 2012 - 03:02 AM

The Find Next functionality doesn't actually find the next match. For example if the edit control contains 'abcdefabc' and you the caret is at beginning of the string, the first find operation for 'abc' finds the 'abc' at offset 0, but then next call to find can't find the 'abc' at offset 6, it always finds the 'abc' at offset 0.

You probably want to use the variant of String.IndexOf() that takes starting position to start searching from.

Additionally, there is an inherent inefficiency using the String.IndexOf() on the Text from the RichTextBox because the underlying unmanaged RichEdit control will have to collect all the text and marshal that to the managed RichTextBox so that a string can be returned. As noted in the C# subforum, it would be more efficient to call the RichTextBox.Find() method. Imagine if you had 64K of text in the control, wouldn't it be better to marshal the 10 character string that you are looking for to the unmanaged code as opposed to marshalling the 64K of text in the RichEdit control.
Was This Post Helpful? 0
  • +
  • -

#4 derekpuleo   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 02-August 12

Posted 08 August 2012 - 09:40 PM

private string _filePath;
private string _oldFile;

Where does that go:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
public partial class Form1 : Form
public Form1()

private void textBox1_TextChanged(object sender, EventArgs e)

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1