Now, we have reached a point where it might be useful to place the data that we have on the form into a text file, so that
we can restore this data and we can make lots of different files to create 'levels'.

The file specifications can include a list of rectangle properties (Left, Top, Width and Height or Right and Bottom) for
the Platform, Wall, and Coin.  The coin has a fixed width and height though, so we only need to have Left and Top for coins.
So, let's make the specification:
The first integer in the file will be the number of platforms, and following this integer will be the Left, Top, Right, and
Bottom of each rectangle in the level.  After these rectangle properties, the next integer will be the number of walls, 
followed by its respective rectangle properties (LTRB).  The next integer is the number of coins, and it will be followed by
Left and Top values only.

OK.  First, let's save what we have there.  Of course, we would not want this in the final product so first, we need to set
up some Conditional Compilation definitions.  Of course, #define statements go at the top of the file.

#define TESTversion
// Remove this line to stop the code from compiling the test version.
Now, let's have a key combination that causes the data on the form to be saved to a file. Let's say Ctrl+S. So, in the KeyDown event.
#if TESTversion
			else if (e.KeyCode == Keys.S && e.Control) 
			{
				savelevel();
			}
#endif
And now, we can save the map layout in the file.
		private void savelevel() 
		{
			System.IO.FileStream fs = new System.IO.FileStream(Application.StartupPath & @"\data.lvl", System.IO.FileMode.Create);
			System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs);

			bw.Write(platforms.Count);
			// Write number of platforms to file.

			foreach (Rectangle platform in platforms) 
			{
				bw.Write(platform.Left);
				bw.Write(platform.Top);
				bw.Write(platform.Right);
				bw.Write(platform.Bottom);
				// Write LTRB to the binary file.
			}
			bw.Write(walls.Count);
			// Write number of walls to file.

			foreach (Rectangle wall in walls) 
			{
				bw.Write(wall.Left);
				bw.Write(wall.Top);
				bw.Write(wall.Right);
				bw.Write(wall.Bottom);
				// Write each wall's LTRB to binary file.
			}

			bw.Write(coins.Count);
			// Number of coins.
			foreach( Rectangle coin in coins) 
			{
				bw.Write(coin.Left);
				bw.Write(coin.Top);
			}

			// Done writing.  Close the filestreams.
			bw.Close();
			fs.Close();
		}
Now, run the program and press Ctrl+S. Close it and look for a data.lvl file in the bin\debug folder. If you see it there and it has a decent file size, then everything is ok. (Mine is 188 bytes)
Now, let's test our loading procedure with some faith: Let's delete all of the platform, wall, and coin initialization code in the load event. That is all of this:
			walls = new ArrayList(100);
			// The list of walls is set up.
			walls.Add(Rectangle.FromLTRB(225, 415, 275, 465));
			walls.Add(Rectangle.FromLTRB(320, 480, 350, thelandheight));
			walls.Add(Rectangle.FromLTRB(350, 520, 380, thelandheight));
			// And three walls are added.
			platforms = new ArrayList(100);
			// Initialize the arraylist to hold up to 100 elements.
			platforms.Add(Rectangle.FromLTRB(50, 415, 200, thelandheight));
			platforms.Add(Rectangle.FromLTRB(100, 465, 225, thelandheight));
			platforms.Add(Rectangle.FromLTRB(150, 515, 250, PFMain.thelandheight));
			// Instantiate the platforms for the level.

			coins = new ArrayList(100);

			coins.Add(new Rectangle(200, 530, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(100, 440, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(116, 440, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(132, 440, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(260, 355, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(230, 365, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(240, 510, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(20, 490, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(280, 400, thecoinsize, thecoinsize));
			coins.Add(new Rectangle(200, 498, thecoinsize, thecoinsize));
			// Ten coins going into the coins arraylist.
And now, we call a LoadLevel() sub that we will complete in a few moments. So:
			loadlevel();
			// Load the level information from the file.
in place of all of that that was removed. It really can go anywhere in the Load event. Now, for the LoadLevel subroutine.
		private void loadlevel() 
		{
			System.IO.FileStream fs = new System.IO.FileStream(Application.StartupPath + @"\data.lvl", System.IO.FileMode.Open);
			System.IO.BinaryReader br = new System.IO.BinaryReader(fs);
			int lv;

			platforms = new ArrayList(br.ReadInt32());
			// First is the number of platforms which will be set as the capacity of the platforms arraylist.
			for (lv = 0; lv < platforms.Capacity; lv++) 
			{
				platforms.Add(Rectangle.FromLTRB(br.ReadInt32(), br.ReadInt32(), br.ReadInt32(), br.ReadInt32()));
				// The LTRB is read from the file.
			}

			walls = new ArrayList(br.ReadInt32());
			// The number of walls precedes the wall data.
			for (lv = 0; lv < walls.Capacity; lv++) 
			{
				walls.Add(Rectangle.FromLTRB(br.ReadInt32(), br.ReadInt32(), br.ReadInt32(), br.ReadInt32()));
				// LTRB read from file again.
			}

			coins = new ArrayList(br.ReadInt32());
			// Number of coins.
			for (lv = 0; lv < coins.Capacity; lv++) 
			{
				coins.Add(new Rectangle(br.ReadInt32(), br.ReadInt32(), thecoinsize, thecoinsize));
				// Create rectangle with the fixed width that all coins have.
			}

			br.Close();
			fs.Close();
		}
Looks simple. And now you'll find our level was generated purely from file.
Now, we'll have to go a bit into our editor crates in order to allow platforms, walls, and coins to be added to the form. We'll allow the mouse to be used to select some rectangle on the form. When the mouse is down, we will set one point of the rectangle. When the mouse is released, we will set another point on the rectangle. While the mouse is down, we will draw an unfilled rectangle connecting the mouse coordinates with the initial point. When the mouse is released, a platform or wall will be drawn. A coin will only be placed at the mouse down. We'll use the P, W, and C keys to determine if we are going to draw a platform, wall, or coin. Notice that we cannot use the rectangle as is, because a rectangle has to have a positive width and height if it is to be drawn. So, we'll use two Points for the mouse coordinates and just use Math.Min and Math.Max to get a decent rectangle from them. Now, let's make our declarations.
		bool ismousedown;
		// Indicates if the mouse button is down.
		Point initialpt, finalpt;
		// The initial and final point of the rectangle that was dragged by the user.
		char modobject;
		// P for platform, W for wall, C for coin.
Since modobject is either 'P', 'W', or 'C', it should be initialized to one of these at the beginning.
			modobject = 'P';
			// Start off the modobject character to be P, representing platform.
Now, ismousedown needs to be set to true in the MouseDown event and false in the MouseUp event. In the MouseDown event, the initalpt is set. In the MouseUp event, the finalpt is set and the platform, wall, or coin is generated. If we are placing a coin (which will be when modobject is 'C', then we don't need the initialpt to try to find a width or a height, since it is predetermined. First, the MouseDown event.
		private void PFMain_MouseDown(object sender, MouseEventArgs e)
		{
			ismousedown = true;
			initialpt = new Point(e.X, e.Y);
			// Mouse is down.  Set the initial point as well.
		}
And now, the MouseUp event.
		private void PFMain_MouseUp(object sender, MouseEventArgs e)
		{
			Rectangle placed;
			finalpt = new Point(e.X, e.Y);
			ismousedown = false;
			// set the final point and indicate the mouse is no longer down.
			// The selection will be added to one of the arraylists we have for the level, depending on modobject's value.

			switch (modobject) 
			{
				case 'P':
					placed = Rectangle.FromLTRB(Math.Min(initialpt.X, finalpt.X), Math.Min(initialpt.Y, finalpt.Y), Math.Max(initialpt.X, finalpt.X), Math.Max(initialpt.Y, finalpt.Y));
					platforms.Insert(0, placed);
					// Add the form to the list at the beginning so that building goes upwards instead of downwards.
					break;
				case 'W':
					placed = Rectangle.FromLTRB(Math.Min(initialpt.X, finalpt.X), Math.Min(initialpt.Y, finalpt.Y), Math.Max(initialpt.X, finalpt.X), Math.Max(initialpt.Y, finalpt.Y));
					walls.Insert(0, placed);
					// Add wall to wall arraylist.
					break;
				case 'C':
					coins.Insert(0, new Rectangle(initialpt.X, initialpt.Y, thecoinsize, thecoinsize));
					break;
			}
		}
And of course, both of those go into an #if TESTversion compilation if block. Don't forget to add the handlers for these two events in the InitializeComponent.
#if TESTversion
			this.MouseDown += new MouseEventHandler(PFMain_MouseDown);
			this.MouseUp += new MouseEventHandler(PFMain_MouseUp);
#endif
We need to add some else ifs to the keydown event so that the modobject change between P, W, and C.
			else if (e.KeyCode == Keys.P) 
			{
				if (!ismousedown) 
				{
					modobject = 'P';
				}
			}
			else if (e.KeyCode == Keys.W) 
			{
				if (!ismousedown) 
				{
					modobject = 'W';
				}
			} 
			else if (e.KeyCode == Keys.C) 
			{
				if (!ismousedown) 
				{
					modobject = 'C';
				}
			}
That has to go within the #if and #endif in the KeyDown Now, let's add something graphical so that we can see where our new rectangle will go. We'll make a rectangle that connects the initialpt with the mouse coordinates.
			if (ismousedown) 
			{
				Rectangle outline;
				Point curse = Cursor.Position;

				curse = this.PointToClient(curse);
				// Get the cursor location relative to the form instead of the screen.
				outline = Rectangle.FromLTRB(Math.Min(initialpt.X, curse.X), Math.Min(initialpt.Y, curse.Y), Math.Max(initialpt.X, curse.X), Math.Max(initialpt.Y, curse.Y));
				// Creates the drawing rectangle.  Now it has to be drawn.
				gfx.DrawRectangle(Pens.Black, outline);
			}
Like that. That can go near the end of the artwork subroutine... but it does have to come before the this.drawonform(). Now, you should be able to customize your levels and add platforms, walls, and coins.