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.
=========================================================================================