Personal C Sharp         by    famsoft.org

Home | Demonstrative Examples | PC# Methods | PC# Reference | Links

Personal C# Reference

                                                                           You are welcomed to use our site for your web search.
                                                                    See the fine products advertised at the bottom of each page too.


                                      PERSONAl C# REFERENCE
                                      =====================

HOW TO START:
===============

You need to install Microsoft ".Net Framework package and development kits, then install
Personal C# software.

Click here for a step by step instructions: How to start

PROGRAMMING TOOLS:
==================
 
pcp: Compiles your file into an executable program (.exe)
     Example: pcp MyProg [Enter]    Compiles your "MyProg.cs" file and
     generates the executable file "MyProg.exe" which can be executed by
     typing      MyProg  [Enter]

pcpr:Does every thing (pcp) does and additionally executes the resulting
     executable file.
     Example: pcpr MyProg [Enter]   Compiles your "MyProg.cs" file and
     executes the resulting "MyProg.exe" file.

pcl: Compiles your file into a library file (.dll)
     Example: pcl MyLibFile [Enter]    Compiles your "MyLibFile.cs" file and
     generates the library file  "MyLibFile.dll".

ln : Line number finder. If you are using NotePad to write your programs, you
     can't easily know the order number of each line in your program. You'll
     have no problem with this until you get a "Compiling error message like
     this:
           a.cs(24,28): error CS1010: Newline in constant

     The error code says that the error is at line 24, character 28. This tool
     displays for you line 24, the 10 lines before it and the 10 lines after it
     when you type:   ln 24  [Enter]

     You maybe wondering how the tool knows which file to display the lines of. This
     will be explained next.

WHAT ELSE THE TOOLS DO?

The tools pcp, pcpr and pcl  are not merely for compiling, they add to your
code some of the repeated items, so you don't waste your time including them
into every program you write. The added items are:

(1) The "using" directives: The following directives are added:

using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Text;
using System.Drawing;
using System.Drawing.Text;
using System.Drawing.Printing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Threading;
using System.ComponentModel;
using System.Windows.Forms;

The "using" directives allow us to write shorter code. For example, the full name of
the Button object is "System.Windows.Forms.Button". Since the "using System.Windows.Forms"
directive is included at the top of the program, we can simply refer to the object using
the name "Button".

If your program contains its own "using" directives, they will be checked, if not
duplicates, will be added to the list (See "Program structure" below)

(2) If your program contains reference to external objects you must add the dll/exe file
paths seperated with commas following the word "assembly" preceded with "//". They will
be read by PC# and used for compiling the program, while neglected during execution.

Example: If your program contains reference to the two objects "test.x","test.y" where
         "test" is their common namespace and the files containing the 2 objects are
         "x.dll" and "c:\\cs\\y.exe", you MUST add this commented line anywhere above the
         "namespace" statement:
                             //assembly x.dll,c:\\cs\\y.exe;
We are also going to see an Example illustrating how a class can instantiate another and
use its fields later in this section.

(3) Additionally, if you are creating "exe" file, the following lines will be added
immediately following class definition statement assuming that your class name is "a":

  [System.STAThreadAttribute()]
  public static new void Main(String[] args) {
    a xx=new a();
    Application.Run(xx);
  }

(4) After making the additions, your program file is copied to the file "pca.cs", compiled
producing the ".lib" or ".exe" files then all aditions are removed, restoring your program
to its original condition before returning it to you.

If a compilation error was found, you'll get the error message telling you at which line
the error was found. Remember that the file we have compiled was not the file you know, it
was the file which has included the additions (the file which has been copied to pca.cs) So, we
need to analyze "pca.cs" to know which line the compiler is telling us about.

So, no matter what your program name is, file "pca.cs" is always a copy of the last
compiled file including additions. This is why you don't need to tell the tool "ln" what
your program file name is. It reads and displays lines of only one file which is "pca.cs".
 

                                        PROGRAM STRUCTURE
                                       ===================

using System.Security;             // Additional "using" directives which are not
using System.Reflection;           // included into the autaomatically added list
                                   // (Already discussed)

//assembly lib1.dll,c:\\prog1.exe; // A commented line including file path for all
                                   // additional objects referenced into your program
                                   // (Already discussed)

namespace Food {                   // namespace (Optional)

  public class Fruits:pcs {        // Class declaration. Class name must match
                                   // program file name

    double price;                  // Variable declarations (Optional)

    public override void init() {  // Method init() (necessary)
      base.init();                 // Must be last statement
    }

    public override void setup() { // Method setup() Necessary only when you
    }                              // like to do operations on the Form like
                                   // resizing or installing Controls

    public override void update() {// Method update() Necessary only when you
    }                              // have Controls installed and want to
                                   // handle their events

    public override void run() {   // Your entire program should be here
    }
  }
}

CLASS DECLARATION:

In order to be able to use PC# methods, you need to extend class (pcs)
If the class name was "Fruits", you must save your program into a file named
"fruits.cs". After the file is compiled, a new file named "fruits.exe" or
"fruits.dll" will be generated depending on your selection.

VARIABLE DECLARATIONS:

As you'll see next, PC# has pre-declared some variables of types int, double
and string. However, if you prefer to use your own variable names, you need
to define them here.

METHOD init():

This method is necessary when you like to set default values like setting the "Text input
and Output devices", error level code or startup block number.

If you include this method into your program, you must add the statement (base.init();) at
its end in order to allow PC# classes to initialize with your default values.

Here are most of the items you can enter in method init():

  public override void init() {
    tia=toa="t";                // text input and output device setup
    eri=3;                      // Error level code (See Error Handling)
    bli=1;                      // start-up block number [See Method run()]
    base.init();                // Initializing PC# classes
  }

METHOD setup():

If you like to operate on the Form, you need to include this method into your program.
Here is what this method may contain:

  public override void setup() {
    j=400;k=300;cm("fs");               // Resize Form to (400,300) Pixels
    ib=true;cm("fa");                   // Turn Form's Auto-Scroll on.
    j=20;k=30;cm("fm");                 // Set Form's Margins to (20,30)
    cs="bt0";i=o=60;cm("i");            // Install Button (bt0)
  }

METHOD update():

Whenever the user activates a control like clicking on a button, an event is
generated. PC# receives the event and calls method update() with the
information it needs which are:

a) Keyname of the Control which has been activated in (cs)
b) The text enterd if the control receives text from user in (cus)
c) The order of the item selected if it cotains selectable items in (cui)

Method update should contain what you like to do when each event occures.
Here is what method update() may contain:

  public override void update() {

    if ("bt0".Equals(cs)) {              // If bt0 clicked
      // do something
    }
    else if ("bt1".Equals(cs)) {         // if bt1 clicked
      // do something else
    }
  }
 
Sometimes handling events received from user is everything we need our program
to do. In such case method run() becomes unnecessary.

METHOD run():

If you are not using Controls, this is where your entire program should be.
Typically, method run() should be made of several blocks. You can force
program execution to jump from one block to another. The variable (bli)
included into method init() determines which block to start execution at.

  public override void run() {
    if (blp==1) {
      // block #1's code
    }
    else if (blp==2) {
      // block #2's code
    }
  }

EXECUTION SEQUENCE:

The first method to execute is init() When the statement base.init() is
encountered, the program is initialized and the form's initial size is set.
Method setup executes next. Your controls are installed and become ready to
receive events. However, method run() immediately executes at the block which
you have requested to start execution at.
The last method to execute is update() which is called only after the user
activates a control.

THE TEXT INPUT AND OUTPUT DEVICES:

The text input device is the device to expect receiving user's input data from.
It can be one of the following:

(1) The Consol. This is the default.

(2) The text screen. To indicate that the "text screen" is your text input device include
    the statement (tia="t";) into method init()

(2) A text command file. To indicate that a file is your text input device include the
    statement (tia="FileName";) where "FileName" is the name of the file. The file can be
    made using NotePad. It should contain each text line user is expected to type followed
    with one [Return] exactly as it could have been done if Text Screen was used.

The text output device is the device to be used for displaying text to user.
It can be one of the following:

(1) The Consol. This is the default.

(2) The text screen. To indicate that the "text screen" is your text output device include
    the statement (toa="t";) into method init()

(3) A text file. To indicate that a file is your text output device include the statement
    (toa="FileName";) where "FileName" is the name of the file. If the file was not
    available it will be created. If it was available. its contents will be erased and
    replaced with the output text.

The Text Screen:

The Text Screen has been developed by PC# to be used as an interface between your program
and the user. It contains a Rich Text Box of about the same size as the Form which can
display text using any color and font. At the bottom, it contains a text field into which
the user enters his response whenever your program instructs him to do so.

The Text screen can also be used by the user independantly from your program. The user can
use it as a Text Editor. He can edit the displayed text, add to it, delete part of it,
change colors and fonts, apply the "cut, copy, paste and/or select all" features, enable or
disable the "Word Wrap" feature or clear the screen. Additionally he can save the text
into a file using plain text or rich text formats. He can also print the text using
selectable fonts.

Your program can also load a file into the Text Screen, save its contents into file or
print them.

Example to show how to use System Consol for text input and output:

class a:pcs {
  public override void run() {
    cm("fe");                      // Eliminate form to allow System Screen to appear
    os="Enter your name: ";tm("i");// Display the string then get user's response
    os="Hello "+os;tm();           // Display "Hello " + the string entered.
    sm("e");                       // Exit program
  }
}
REMARK: User can terminate this program whenever he wants by pushing the [Control] & [Break]
        keys simultaneously.

Example to show how to use files for text input and output:

We are going to use Example 4, Group I in which the user selects "r", "g" or "b" from a
menu causing the phrase "Hello World" to be displayed in "red", "green" or "blue"
respectively. Method run() will stay the same. Method init() will be modified to indicate
that file "input.txt" contains the "user supplied text" and file "output.txt" is to be
used for output text.

Using NotePad, we'll create the input file and type the following into it:
r [Enter]
e [Enter]
This means that we'll select "r" from the menu, and after the message is displayed in red
and the menu appears again, we'll select "e" to exit.

Then we'll modify method init() as follows:

  public override void init() {
    tia="input.txt";                      // Use file "input.text" for input
    toa="output.txt";                     // and file "output.txt" for output
    bli=1;
    base.init();
  }

After running this program, here are the contents of file "output.txt":
-------------------------------------------------------------------------------------
                                         MENU

  (R) Red.
  (B) Blue.
  (G) Green.
  (E) Exit.

Type your selection into the text field at bottom then hit the [ENTER] key.
Selection :r
Hello World.
                                         MENU

  (R) Red.
  (B) Blue.
  (G) Green.
  (E) Exit.

Type your selection into the text field at bottom then hit the [ENTER] key.
Selection :e
--------------------------------------------------------------------------------------
THE GRAPHICS OUTPUT DEVICE:

During program initialization, the Form size is set, then method setup() is called to
see if you want to make any changes to the Form or to install Controls into it. A
reference to the Form's Graphics object is then obtained. The variable storing the
reference is (gra) It is public, so it is available to your program. However, we don't
like to draw directly on the form.

Also, during initialization, we create a transparent bitmap object of the same size as
the Form which we use for drawing. The reference to this bitmap object is in (bio) which
is also public. Also at initialization we make (bio) the Graphical output device meaning
that (grp) "the present Graphics object reference" becomes its reference, and this means
that anything we draw is drawn on it.

At any time, as your program needs, you may make your "Present bitmap object (bip)" the
graphical output device replacing (bio) by calling gm("sdb") and you may return (bio) as
the Graphical output device by calling gm("sdd")

INSTANTIATION:

This Example shows how one class can inistantiate another and access its fields and methods.

// ---------------------------------- Class a ----------------------------------------
public class a {                                 // 1st class. Library class (dll)
  public string af="This is field af of class a";// public field to allow accessablity
}

// ---------------------------------- Class b ----------------------------------------
//assembly a.dll;                                // Commented assembly line must include
                                                 // file paths for objects it accesses.
public class b:pcs {                             // Executable class extend PC#
  a ao=new a();                                  // Creating an instance of class a

  public override void init() {
    toa="t";                                     // Select "text screen" for output
    base.init();
  }

  public override void run() {
    os="This is method run() of class b";tm();   // display identity message
    os=ao.af;tm();                               // display class a's field
  }
}
// COMPILING: Compile class a with the command "pcl a"
//            Compile and run class b with the command "pcpr b"

USING THE COMMAND MODE ARGUMENTS:

You can obtain the Command mode arguments from method dm()  You need to know that the
program name is always available as parameter number zero, so parameter count cannot
be less than 1.

Here is an example which after compilation, creates the executable file "a.exe" which you
can run with 3 different choices, as folloows:

a   [Enter]  Starts program execution at block # 0
a 1 [Enter]  Starts program execution at block # 1
a 2 [Enter]  Starts program execution at block # 2


public class a : pcs {
  public override void init() {
    tia=toa="t";
    dm("pc"); if (o<2) bli=0; // Get par count If =1 (no parameters given) request block 0
    else {
      i=1;dm("p");om("ti");   // Get parameter # 1, convert to int
      bli=o;                  // Use it as the block number to start at
    }
    base.init();
  }
  public override void run() {
    if (blp==0) {
      os="Executing code in block #0.";tm();
    }
    else if (blp==1) {
      os="Executing code in block #1.";tm();
    }
    else if (blp==2) {
      os="Executing code in block #2.";tm();
    }
  }
}

                                   NAMING VARIABLES
                                   ================

NAMING THE VARIABLES YOU USE IN YOUR PROGRAM: You have two choices:
=============================================
(1) Define and use meaningful named variables like name, price or address.
Make sure they are at least 4 characters long in order to avoid collision
with PC# public names.

(2) Use variables from the pre-defined "one char + type code" list which
have been declared public and set for you to use.  They are:

public int a,b,c,d,e,f,g,h,l,m,n,p,q,r,s,t,u,v,w,x,y,z;
public double bd,cd,dd,ed,fd,gd,hd,ld,md,nd,pd,qd,rd,sd,td,ud,vd,wd,xd,yd,zd;
public string bs="",ds="",es="",gs="",hs="",ms="",ns="",ps="",qs="";
public string rs="",ss="",ts="",us="",vs="",ws="",xs="",ys="",zs="";

VARIABLES YOU USE TO EXCHANGE DATA WITH PC#:  Names of these variables have
been selected to make your job as simple and easy as possible in addition to
minimizing human errors.

Names of all public variables are made of one or two chars + type indicator.
The "one char + type" var's are used to represent simple types, like numbers
and strings. The "two chars + type" var's are used to represent objects and
their fields.

The "one char + type" var's use the following type indicator codes:

   i or none = int    f = float    d = double    b = bool
   c = char    s = String    y = byte    r = short    l = long

The "two chars + type" var's use the same type codes in addition to:

   p = present object     a = applet-wide or default object.

Present object means the object we are currently working on. If for example
your program has called the Controls method cm() to set a value for the
button "bt1",you expect after the method's completion that (btp) refers to the
button object and (clp) refers to the button's color.

Applet is actually a Java term. We mean by "applet-wide var" a var which
represents a default value. For example (cla) is the default color which all
text will be displayed into if no color has been specified.

All single value variable names are made of "lower case" chars and all array
names are made of "upper case" chars. There are no names which contain a mix
of lower case and upper case chars.

GENERAL USE VARUABLES (GUV's):
==============================
They are "one char + type" var's. Their base
character can be "i", "j", "k" or "o".

Generally, (i,j,k) based GUV's are used by your program to supply methods with
data and (o) based GUV's are used to supply data from the methods back to the
program. However for simplicity, in some cases (o) based GUV's are used for
both jobs. For example Method um("u") which does "upper-casing" receives a
string in (os), upper-cases its letters and returns it back in (os). This have
allowed us to write a code like this:
    os="hello world  ";om("c");om("u");tm();
All 3 methods use (os) for both input and output. Their functions in order are
to "Trim and remove non text chars", "Upper-case" and "display" the string.

Here are all the GUV's and their declarations:

  public int i,j,k,o,oi;
  public float lf,jf,kf,of;
  public double id,jd,kd,od;
  public byte oy;
  public short or;
  public long ol;
  public bool ib,jb,kb,ob;
  public char ic,jc,kc,oc;
  public string ls="",js="",ks="",os="";
  public object oo=null;

You may have noticed that (is) and (if) have been replaced with (ls) and (lf).
This is because "is", "if" are both C# keywords.

IMPORTANT RULE: All "i,j,k" based GYV's are reset before your program starts
and at the end of every method. We mean by reset that all numerics are set to
zeros, all strings are set to "" (empty string), all boolean vars are set to
"false" and all objects are set to "null".

This means that they are guaranteed to be always reset. The only time they are
asigned different values is immediately before your program calls a method. We
advise you to make the asignment and the method call on the same line and not
to use the "i,j,k" based GUV's for any purpose other than supplying the
methods you call with data. To demonstrate the importance of this rule,
consider this code for drawing a square at the screen center:

      lf=of=100;gm("crd");                        // Create & draw 100X100 rect at center

Method gm("crd") draws a rectangle with its width and height assigned to (lf,of), its center
displacement relative to the form's center assigned to (jf,kf), its shear factors assigned
to (id,od) and its rotation angle assigned to (ad) Yet we have only assigned values to
(lf,of) and forgot about everything else. This was because we can guarantee that all the
variables which we have not assigned values to are assigned zeros.

GENERAL USE ARRAYS:
===================
They are also made of "one char + type" and are used in the same manner as GUV's when
multiple values are needed for method's input or output.

 int[] I=new int[guh];int[] J=new int[guh];int[] K=new int[guh];int[] O=new int[guh];

           float[] LF=new float[guh];float[] JF=new float[guh];
           float[] KF=new float[guh];float[] OF=new float[guh];

         double[] ID=new double[guh];double[] JD=new double[guh];
         double[] KD=new double[guh];double[] OD=new double[guh];

         string[] LS=new string[guh];string[] JS=new string[guh];
         string[] KS=new string[guh];string[] OS=new string[guh];

           bool[] OB=new bool[guh];Object[] OO=new Object[guh];
            char[] OC=new char[bch];byte[] OY=new byte[bch];

The static var's (guh) and (bch) are not public var's. However, you can still modify their
values using methods dm("hg") and dm("hb").

OTHER USES "ONE CHAR + TYPE" VAR'S:

In addition to the "one char + type" var's which are used as the GUV's and the ones
pre-defined and assigned for your program to use, few are also declared public and
used for other purposes. They are:

cs: Keyname for a "Controls".
fs: Keyname for a "File".
ad: Rotation angle (in Graphics)

THE "TWO CHAR'S + TYPE" VAR'S:
==============================

RULES FOR SELECTING THE TWO CHAR'S:
(1) The first char is the first letter in the object's name.

(2) If the name is made of one word, the second char is the next non vowel letter in the
name. If the name is made of more than one word, the second char is the first letter of
the second word.

(3) If the rules above, indicate that more than one object should be named the same, the
most commonly used object gets the name and the rest use the third non vowel letter as their
second char.

WHAT IS THE PRESENT OBJECT?:

Let us consider this short program:

lf=of=100;gm("crd");   // Create & Draw a square with each side=100 pixels at center
lf=of=200;gm("ced");   // Create & Draw a circle with diameter=200 pixels at center

When the first line was executed, PC# created a GraphicsPath object, added a square
to it then drew it on the Graphical output device.

When the second line was executed, PC# created also a GraphicsPath object, added a circle
to it then drew it on the Graphical output device.

In order to operate on an object, you need to create references to them and if unused
objects stay referenced, they don't get "garbage collected", so they stay in the memory
wasting resources.

Your program wanted a square to be drawn, so a GraphicsPath object and a reference to it
have been created. If your program wanted to do any other operation on that object at the
next step, it could have been executed properly since the object and its reference have
been available.

But, your program wanted to create a new object of the same type, so what should PC# do?
Should it keep the old object referenced because you may return to it later or should it
dispose it to free its resources? The answer is neither one.

PC# uses only one name to reference all GraphicsPath objects which is (gpp), "The present
GraphicsPath object ref." When the first line was executed, (gpp) became a reference to
the first object. When the second line was executed, (gpp) became a reference to the new
object leaving the first object unreferenced, unless your program has created another
reference as will be discussed shortly.

So as far as PC# is concerned, only one object of each type is referenced at any moment
which is the last one used. Now if you must access the square object after the circle
object has been created, you need to modify your program as follows:

lf=of=100;gm("crd");   // Create & Draw a square with each side=100 pixels at center
GraphicsPath MyGP=gpp; // Make my new var a ref to the first object
lf=of=200;gm("ced");   // Create & Draw a circle with diameter=200 pixels at center
gpp=MyGP;              // Return gpp as a ref to the first object

PC# does not dispose any object or force garbage collection. Limited referencing does
it all. You should also design your program so it requires minimum referencing. If you
need to force garbage collection at any point use um("g");

Memory management is only one advantage of using the "Present Object" strategy. Another
advantage is name unification. There is only one name for each object type. No matter, if
you are working on a rect, a circle or an arch, there is only one name to use for any
operation on their objects which is (gpp) This makes your programming simpler and less
subject to errors.

                           WORKING WITH PC# OBJECTS

You don't need to know how to work with objects in order to write programs
with PC#. Actually, none of the demonstrative examples included operations on
objects. However, we know that when you learn more and become professional,
you'll like to get PC# to do things beyond what it normally does and this
requires obtaining referencies to internal objects.

How to obtain reference to an object: You call the method which handles the
object at mode "O" (this is upper case "O") You need to supply no other
arguments to get all objects supplied by the method at once except for methods
cm() and fm()

Method cm() requires the keyname of the Control you are interested in,
assigned to (cs) and method fm() requires the keyname of the File you are
interested in assigned to (fs)

Method um() at mode "O" lets you know if the object is null or not to help you
avoid the Exception generated when you operate on a null object. Here is an
example:

gm("O");              // Get all present objects related to drawing
ks="utp";um("O");     // Check to see if (utp) is null
if (!ob) {// do an operation on (utp)}
                      // If (utp) is not null do the operation

PUBLIC OBJECTS:
==============

REF                 OBJECT DESCRIPTION                   STARTUP STATE     TO GET
===  =================================================  ================  ==========

GENERAL:

clp  Present Foreground or first Color object            null              no action
clo  Present Background or second Color object           null              no action
exp  Present Exception                                   null              no action
thp  Presently created Thread object                     null              no action
tha  Thread Object into which program is running         null              available
HTP  Present Hatchtable object                           available         available

CONTROLS:

btp  Present Button object                               null              cm("O");
lbp  Present Label object                                null              cm("O");
cbp  Present CheckBox object                             null              cm("O");
rbp  Present RadioButton object                          null              cm("O");
chp  Present ComboBox object                             null              cm("O");
lsp  Present ListBox object                              null              cm("O");
tfp  Present Text Field object (TextBox type)            null              cm("O");
tap  Present Text Area object (TextBox type)             null              cm("O");
rtp  Present RichTextBox object                          null              cm("O");
pnp  Present Panel object                                null              cm("O");
mmp  Present MainMenu object                             null              cm("O");
cmp  Present ContextMenu object                          null              cm("O");
ttp  Present Tooltip object                              null              cm("O");

DRAWING:

grp  Present Graphics object                            (bio) Graphics     gm("O");
gra  The Form's graphics object                          available         available
gpp  Present GraphicsPath object                         null              gm("O");
bip  Present Bitmap object                               null              gm("O");
bio  Bitmap object used as Default graphical device      available         gm("O");
spp  Present Solid Pen object                            Black,1 pixel     gm("O");
sbp  Present Solid Brush object                          Black,1 pixel     gm("O");
lgp  Present Linear gradient paint bush object           null              gm("O");
rgp  Present Radial gradient paint bush object           null              gm("O");
tbp  Present Texture paint brush object                  null              gm("O");
utp  Present Unit's Affine transform                     null              gm("O");
pdp  Present PrintDocument object                        null              gm("O");

FILING:

fsp  Present FileStream object                           null              fm("O");

NETWORKING:

tcp  Present TcpClient object                            null              nm("O");
nsp  Present NetworkStream object                        null              nm("O");

TEXT:

rta  Text Screen's RichTextBox object                    null              tm("O");
tfa  Text Screen's TextBox object                        null              tm("O");
mma  Text Screen's MainMenu object                       null              tm("O");
lba  Text Screen's Label object                          null              tm("O");
pna  Text Screen's Panel object(Contains lba,tfa)        null              tm("O");

PUBLIC METHODS:
==============

All public methods names are made of "one char + type code" The type code for a method
is 'm'.  They can all be accessed with one string argument which sets the "mode". A
method can do variety of operations depending on the mode it is accessed at.

We know that most people who like programming also like innovation. So, we have made it
possible for you to override all public methods. You can add new modes to any method and
you can also replace PC# code for a mode with your own code.

Let us see an example which shows how to create a library class which sets between your
programs and PC# classes. Your programs extend the library class and the library class
extends (pcs). Whenever one of your programs calls a method which the library class
contains and can execute, it will be executed there. If it could not be executed there,
it will be sent to the underlaying PC# method for execution.

The library class will contain an overriding tm() method which introduces two new modes:

(1) Mode "bc": In this mode your program supplies a color code in (cls) and the method
    changes the text screen background color to match it.

(2) Mode "dh:: In this mode, your personal letter head is displayed at the center.

public class mylib : pcs {
  public override void tm(string mode) {            // Overriding method tm()

    if(mode.Equals("bc")) {                         // If "background color" was selected
      os="";tm("d");                                // Obtain object for selected color
      rta.BackColor=clp;                            // Set Text Screen background color
      cls="S9";                                     // Restore original color
      um("c");                                      // Clear (reset) all GUV's
    }
    else if (mode.Equals("dh")) {                   // If "display letter head" selected
      fns="trb24";cls="b0";                         // Use blue color and size 24 font
      os="                            My Name";tm();// Display name
      fns="trb12";                                  // Reduce font size, display address
      os="                                                              123 Main st.";tm();
      os="                                                         MyCity, CA 12345";tm();
      os="";tm();tm();                              // Skip 2 lines
      cls="S9";fns="trb10";                         // Restore original font and color
      um("c");                                      // Clear (reset) all GUV's
    }
    else base.tm(mode);                             // If any other mode selected, execute
                                                    // base method.
  }
}

The library class should be saved into a file named "mylib.cs", then compiled with the
tool (pcl) producing the library file "mylib.dll".

//assembly mylib.dll;                                // Include "mylib.dll" file
class a:mylib {                                      // Program class extends mylib
  public override void init() {
    toa="t";                                         // Select text screen for text output
    base.init();
  }
  public override void run() {
    cls="p7";tm("bc");                               // Set background color to Light Pink
    tm("dh");                                        // Display my letter head.
  }
}

When you compile and run this program using (pcpr), the text screen will show in pink
color and your letter head will appear at the top of the screen.

                            SETTING COLOR AND FONT
                            ======================

SETTING THE COLOR: Some items require specifying one color and some other
items require specifying two colors. You specify one color when you create
a pen or solid brush to paint with, and when you display text on the
"Text Screen". You specify two colors when you create Gradient Paint Brush
or when you are creating a control which requires foreground and background
colors.

A color is specified with 4 numbers (0-255) each representing the Red,
Green, Blue and Opacity components of the color.

THE COLOR CODE:

Used to simplify color setup. It is constructed of one character
followed with 2 digits. The character represents the color, the first digit
represents the shade and the second digit represents the opacity. Let us look
at an example before we go further.

"y11" Means Yellow color made lighter by 11% (1 on a scale of 0-9) and
11% opaque. When we say lighter by 11% we mean mixed with white color at a
ratio of 11% white, 89% yellow.

Now what to do if we want the color to be darkened by 11%? The answer is to
use upper case "Y" instead of lower case, so it becomes "Y11".

So, "r19" means 11% whitened, fully opaque red while "R19" means 11% darkened
fully opaque red. Both "b09" and "B09" represent the same color which is fully
opaque pure blue. "g00" means fully transparent pure green.

To make it extra simple, the opacity digit is optional. If you eliminate it,
the color will be fully opaque. So both "m0" and "m09" mean the same color
which is "fully opaque, Pure Magenta".

The character which represents the color can be:

Red  (r or R)            Green   (g or G)           Blue   (b or B)
Cyan (c or C)            Magenta (m or M)           Yellow (y or Y)
Pink (p or P)            Orange  (o or O)           Light Blue (l or L)
                         Shade   (s or S)

Shade means gray, Sorry "g" has been assigned to "Green".
"s9" means white, "S9" means black. Both "s0" and "S0" mean the same color
which is "Gray".

For applications where two colors are required, a color code made of the
concatenation of two single color codes are used.

As an example "r0y0" means first color is red and second color is yellow.
If we are using it to set the color of a control, the first color is the
foreground color and the second color is the background color.

You can also specify opacity changing it to "r09y05" if you like.

HOW TO SPECIFY THE COLOR:

(1) Using the color code: assign code to (cls)
    Examples: cls="b2"    cls="p05"   cls="g0s9"    cls="r09y05"

(2) Using color components: Assign "c" to (cls) and enter the color components
    into array CLI[]. Array CLI[]  should contain either 4 rows or 8 rows.

    If you are entering two colors, enter the "red, green, blue, opacity"
    components of the first color into the first 4 rows and the same
    components of the second color into the last 4 rows.

    If you are entering a single color, either recreate array CLI[] as a
    4 rows array or use the first 4 rows and make sure the last 4 contain
    zeros.

    Examples: cls="c";CLI=new int[]{255,0,0,255,255,255,0,125};
              cls="c";CLI=new int[]{0,0,150,255};          


(3) Supplying the color objects: Assign "o" to (cls) and make (clp) a
    reference to the first color and (clo) a reference to the second color.

(4) Using the color dialog: If you like the user to select the color, call
    cm("dtc") in order to display the color dialog and make (clp) a reference
    to the selected color object.

    Example: // If one color:
             cm("dtc");cls="o";
             um("co"); // Reset "o" based var's

             // If 2 colors:
             os="Please select Background Color.";cm("d");
             cm("dtc");clo=clp;
             os="Now, Please select Foreground Color.";cm("d");
             cm("dtc");cls="o";
             um("co"); // Reset "o" based var's

    Remark: The dialog returns values in "o" based var's which may cause
            problems with next method call. So resetting them after the call
            is a good practice.
          
SETTING THE FONT:  You may make your font setup simpler if you choose one of
                   the 3 fonts:

(1) Times Roman: Classic font which looks great.
(2) Courier: Mono-spaced font. All its char's occupy equal space which makes
    it suitable for applications which require alignment like making tables.
(3) Helvetica (Sans Serif): A simple font which also looks good.

However, you can use any other font as long as you have its object.
 
THE FONT CODE:

The font code is made of:
(1) Two characters representing the font name. They must be:
        tr=Times Roman            cr=Courier              hl=Helvetica

(2) Any combination of the following one char codes:
      p=Plain     b=Bold     u=Underlined     i=Italic     s=Striked out
    If none of the codes have been included, 'p' will be used as default.

(3) A number representing the font size.

Examples:
  "tr12"=Times Roman, Plain, size 12       "crb10"=Courier, bold, size 10
  "trbuis24"= Times Roman, bold, underlined, italic,striked out, size 24.

HOW TO SPECIFY THE FONT:

(1) Using the font code: assign code to (fns)
    Examples: fns="trb14";

(2) Supplying the font objects: Assign "o" to (fns) and make (fnp) a
    reference to the font object.

(3) Using the font dialog: If you like the user to select the font, call
    cm("dtf") in order to display the font dialog and make (fnp) a reference
    to the selected font object.

    Example: cm("dtf");fns="o";

 

                              ERROR HANDLING

HANDLING COMPILING ERRORS:

If there has been an error in your code which the C# compiler could detect, you'll get
an error message like this:

           a.cs(24,28): error CS1010: Newline in constant

As indicated, the error is at line 24, char 28. To display this line type:

                         ln 24 [Enter]

Here are some of the compiling errors which you may see:

(1) Newline in constant: Most of the times, it means that the line contains a string
    leteral with missing last double quote.

(2) 'pcs.a' is a 'field' but is used like a 'type': This could happen if (a) was your
    class name and you saved your program under a different name.

(3) error CS1002: ; expected: You did not terminate the line with (;)

(4) error CS1026: ) expected: The number of opening ('s exceeded the number of closing
    ones.

(5) If you get an unexpectedly large number of compilng errors, expect a missing brace.

How to troubleshoot compiling errors (Can be helpful with Runtime errors too):

An error in one line is easy to fix, but when you get several error messages at different
lines, it becomes harder especially because only one error can be the cause of them all.
Use the following two methods to reach the error code:
 
(1) Keep eliminating parts of the program by placing some program lines between
    (/* and */)
(2) Add a "Console Write" statements at different locations of your program to display
    the value of the variable(s) which you may suspect to be related to the error cause.
    Here is how a sample "Console Write" statement may look like:

                      Console.WriteLine("At block 2 top, os="+os);

RUNTIME ERRORS:
 
There are 4 levels of Runtime error handling. You select the level by assigning 0:3
to the int var (eri) into method init()  The default is (eri=2;) Here is what you expect
when selecting each of the 4 levels:

Level 0: At this level you handle errors by yourself. Whenever a Run Time
Exception occures, PC# catches it, assigns the Exception object to (exp)then
throw it back to your program, so you can work on it.

Level 1: At this level PC# catches the Exception, displays the Exception
message, the method and mode which has caused the Exception and the value of
all related variables when the Exception occured then terminates the program.

Level 2(default): At this level PC# checks for errors before they occure. Each
time you call a method, PC# analyzes all the variables you have supplied. If any
of them was found to be beyond expectation, it displays an error message to
let you know which one was wrong and at which method and mode then terminates
the program. If PC# could not detect the problem, it will then do whatever it
does if level 1 was selected.

Level 3: At this level PC# does everything the same as in level 2.
Additionally, it helps you in tracing program execution, by displaying all
methods your program calls one by one until an error occures or the
program terminates normally.

The program runs the fastest at level 0 and it slows down as you go up in
level. The best you can do, is to start at high level so you can debug your
program easily, then keep going down in level as your program becomes better.

Example: We are going to use the example on Graphics in which we read back
a bitmap object which was saved into "jpg" file before. This time, we are
going to supply no readable name for the file in order to see how this error
is going to be handled.

(a) Using Error level 0:

public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    eri=0;                                 // ERROR LEVEL 0
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    try {                                  // "Try {}" encloses the code where exceptions
      fls="";gm("blf");                    // may occure. The file name string (fls) is
                                           // intentially empty to cause an Exception.
      gm("br");                            //
    }
    catch {                                // In the catch statement, the object we are
      Console.WriteLine("Exception: "+exp.Message);
    }                                      // interested in is (exp) which is for the
  }                                        // initial Exception.
}
----------------------------------------------------------------------------------------
Execution of the program, caused the display of this message on the System
screen:

Exception: The path is not of a legal form.
=========================================================================================
(b) Using Error level 1:

Now, modify the program by replacing (eri=0;) with (eri=1;)

----------------------------------------------------------------------------------------
Here is what we get in this case:

  ------------------ Immediately before the Exception ----------------
  cls=S90  fns=  sts=rrc  js=  ks=  os=
  jf=0  kf=0  kf=0  of=0  id=0  od=0  ad=0  ib=False  ob=False  fls=
----------------------------------------------------------------------
PC# Error gm("blf"); The path is not of a legal form.
------------------------------------------------------------------------------

So, we have got the same Microsoft message "The path is not of a legal form."
in addition  to informing us that gm("blf") is the cause. Also, the display of
most var's which method gm() works with and their values at the moment the
Exception has occured can also help. As you can see (fls= ) is one of them.
Exception: The path is not of a legal form.
=========================================================================================
(c) Using Error level 2:

Now, modify the value of (eri) to (eri=2;)

----------------------------------------------------------------------------------------
Here is what we get in this case:

PC# Error gm("blf"); Unreadable file name.
----------------------------------------------------------------------------------------
We have received a more informing message this time and the program was
terminated before the Exception could happen.
=========================================================================================
(d) Using Error level 3:

Now, modify the value of (eri) to (eri=3;)

----------------------------------------------------------------------------------------
Here is what we get in this case:

gm("sdd");gm("e");gm("blf");
PC# Error gm("blf"); Unreadable file name.
----------------------------------------------------------------------------------------
We have received the same message as in level 2. Additionally we have got a
method execution trace from the start until the point the error was detected.
You may be wondering where gm(sdd") and gm("e") came from. They have been
executed internally during the initialization of PC# classes.
=========================================================================================