DESKTOP APPLICATION REFERENCE
=====================
TO START:
=========
You need to install Microsoft ".Net" Framework package and development kits,
then install Personal C# software. Click on the link above to know how.
RECOMMENDED STUDY SEQUENCE:
===========================
(1) Demonstrative examples - Desktop applications.
(2) Desktop application reference.
(3) Demonstrative examples - Web applications.
(4) Web application reference.
A printed copy of "Personal C Sharp public methods" should be looked at during
the study.
Does Personal C sharp software change my system environment setup permanently?
==============================================================================
No. Unlike other softwares, Prsonal C Sharp does not modify any of your system environment
variables permanently when you install it. Each time you open a new "Command mode" window and
attempt to compile a file, PC# applies temporary modification to the system %PATH% in order to
make the .NET and PC# files accessable. This modification ends when you close that window.
SETTING SCREEN DENSITY:
=======================
If you feel that our pages don't look proportional to your monitor's screen, the reason is that
your display resolution setup does not match ours. We set it at (800 X 600 pixels) which is the
lowest position. At this setting, drawings and text appear as large as they can be which is the
best for your sight.
To set your display resolution:
-------------------------------
a) OLDER VERSIONS OF WINDOWS: Right click at any place on desktop, select "Personalize" or
"Display Properties". Click on "Display Settings" and slide the resolution pointer to your
desired position then click on [Apply], [OK].
b) WINDOWS 10: Click on [Start][All apps][Windows System][Control Panel][Appearance & Personalization]
[Display][Adjust Screen Resolution] Set Resolution as necessary then click on [OK].
GETTING THE MESSAGE "ACCESS IS DENIED" WHEN ATTEMPTING TO SAVE A FILE:
======================================================================
With each new version of Windows, security becomes tighter. You like to give your Windows utilities
the administrator privilege so you can use them to save files without getting the "Access is denied"
message. Here is how to do that to "Notepad" in Windows 10:
(1) Click on [Start][All apps][Windows Accessories][Notepad].
(2) On the taskbar, right click the Notepad icon then right click on [Notepad] and select [Properties]
When the properties window appear, click on [Advanced] and check "Run as Administrator" Then
click [OK][Apply][OK].
(3) Right click the Taskbar's Notepad icon again and select "Pin to taskbar".
What else to do if this could not solve the problem?
----------------------------------------------------
With most files and folders, you should have no more problems. However, if problem did not get solved,
try the following procedures in order:
(1) Give the command mode window the administrator privilege in the same manner.
(2) Give your ".exe" file the administrator privilege also.
(3) Using the "File Explorer" browse to the directory which contains the file you want to save. Right
click on the file and select "Properties". Click on the security tab. You should see user groups
like:
Adminstrators
Users
IIS_IUSRS
Trustedinstaller
Edit their permissions and try to give them higher permissions on that file if allowed.
HOW TO OPEN COMMAND MODE WINDOW:
================================
a) Using old versions of Windows: [Start][All Programs][Accessories][Command Prompt]
b) Using Wondows 10: [Start][All Apps][Windows System][Command Prompt]
You can also give it Administrator privilege and pin it to taskbar as explained above with Notepad.
PROGRAMMING TOOLS:
==================
pcp: Compiles your file into an executable Console application (.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] at the Console.
pwp: Compiles your file into an executable Windows application (.exe)
Example: pwp MyProg [Enter] Compiles your "MyProg.cs" file and
generates the executable file "MyProg.exe" which can be executed by
clicking the file name or icon.
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 preceding it and the 10 lines following 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, pwp, 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.Net.Sockets;
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;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
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
"Class Definition" 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. Notice that there should be no space between "//" and "a".
(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 ".dll" or ".exe" files then all additions 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".
Can PC# tools compile any C# code?
==================================
Yes. Our tools internally use the C# compiler which came with the .NET software development
kit which you have downloaded from Microsoft at your computer. This means that they can always
compile any C# code upto the version of the .NET framework which you have.
Can PC# tools compile a class which contains "unsafe" methods?
==============================================================
Whenever you like to speed-up your PC# program execution or to call a system API function within
your program, you may need to use "unsafe" code. Tools "pcp", "pcl" and "pwp" can compile a
file which contains "unsafe" methods or blocks, but you must do the following:
Add the commented word "unsafe" anywhere on your class declaration line like this:
public class FileRead : pcs { // unsafe // Read a file using "kernel32" functions
How to compile a class file which contains its own Main() method:
=================================================================
If you don't like our tools to add method Main() or to add any using directives follow the
class name with a space and the 2 letters 'na' (for 'No Additives') when you call our tools.
For example, if class MyProg contains its own method Main() and all the using directives it needs
into file "MyProg.cs", you should call the tools as follows:
pcp MyProg na [ENTER] To compile it producing the executable file MyProg.exe
pcpr MyProg na [ENTER] To do same as above in addition to running the executable file.
pwp MyProg na [Enter] To compile it producing the window executable file MyProg.exe
REMARK:
-------
The commented lines which start with the word //assembly followed with the file paths of all
objects which are referenced into your class are necessary even if you supply your own Main()
method and using directives.
How to avoid confusing our compilation tools:
=============================================
When you use our tools to compile a class which has not been made for PC#, you need to know the
following:
(1) Our tools do not analyze your entire class file. They analyze only the small section which
lies between the top of the file and the class declaration statement. This section contains
any 'using directives' which you may like to add and the location of any object which is
referenced into your class.
So, you should do your best to make this section similar to ours in order to avoid confusing
our tools. The rest of your file should not worry you since it's not analyzed.
(2) Our tools use the C# compiler which is available at your computer. So it can compile any C#
code upto the version which you have downloaded unless the (dll) file of one or more of the
.NET assemblies used by your program could not be found into the "refs.txt" file which is
available into the "System" subfolder of your working directory. We'll show you how to add
the missing assemblies to that file next.
(3) If your class file contains method main(), see the section above under the title:
"How to compile a class file which contains its own Main() method"
===============================================================================================
The refs.txt file
=================
You already know how to supply the file locations of the objects which are referenced into your
class. But how are the file locations of the .NET assemblies supplied? They are supplied through
file refs.txt which is located into subfolder "system" of your working directory.
All Personal C Sharp's compiling tools read the 2 lists of file pathes, the one you supply
(preceded with //assembly and placed above the class declaration statement) and the ones
contained into that file. They combine the 2 lists together and supply the combined list to the
compiler. In fact, if you eliminate the '//assembly' statements and add your list to the
"refs.txt' file instead you'll be accomplishing the same.
How is the refs.txt file generated:
-----------------------------------
The compiler of the .NET version 2 does not require any entry into this file since it knows where
version 2 assemblies are. Version 3 and version 4 compilers don't know where the newly added
assemblies are, so they require entries into this file.
You have generated this file automatically during startup when you created all Personal C.
Sharp's tools and files. You can also regenerate it at any time using class (pcs)'s menu. To
reach that menu, use command mode to browse to your working directory and type:
pcs [ENTER]
Select [A] from the menu to automatically generate the correct file contents for your computer's
setup and '.NET' installation.
If you have the .NET version 2, this file should be empty unless you add something to it. This is
because the compiler knows where version 2's assemblies are.
If you have downloaded the .NET version 3.5 on a computer with vista operating system and drive
(c:) has been the root drive, the resulting file contents are expected to be:
-----------------------------------------------------------------------
C:\progra~1\refere~1\Microsoft\Framework\v3.0\PresentationCore.dll
C:\progra~1\refere~1\Microsoft\Framework\v3.0\PresentationFramework.dll
C:\progra~1\refere~1\Microsoft\Framework\v3.0\UIAutomationTypes.dll
C:\progra~1\refere~1\Microsoft\Framework\v3.0\WindowsBase.dll
C:\progra~1\refere~1\Microsoft\Framework\v3.0\System.Workflow.ComponentModel.dll
C:\progra~1\refere~1\Microsoft\Framework\v3.0\System.IdentityModel.Selectors.dll
------------------------------------------------------------------------
The file pathes generated for your computer could have been different.
Troubleshooting the refs.txt file:
----------------------------------
The menu may have failed to find some assembly pathes at your computer and may have failed to
generate the entire file if it could not have found some utilities which it does its job with.
If your file contains incorrect or missing assembly pathes and you have used one of our tools
to compile a class, you could have received an error message like this:
-----------------------------------------------------------------------
error CS0012: The type 'System.Windows.DependencyObject' is
defined in an assembly that is not referenced. You must add a reference
to assembly 'WindowsBase, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35'.
-----------------------------------------------------------------------
This tells you that the path for the file which contains the "WindowsBase" assembly is either
incorrect or missing. You can expect the name of that file to be "WindowsBase.dll". So search
for it and add or correct its path. You can edit the 'refs.txt' file using NotePad.
REMARK:
=======
Personal C Sharp tools use "Batch Files" internally. If you are not familiar with those old
script files, a name like "progra~1" which is included into the path list above may be confusing
to you.
Old Microsoft operating systems used to limit the length of a file name to 8 characters. Later,
newer operating systems have eliminated that restriction allowing longer file names and allowing
spaces within file names. Batch files have been made to handle the new file names with a special
formula.
If the file name was longer than 8 char's, only the first 8 char's are recognized, the rest
means nothing to a batch file. But this could cause a problem when the first 8 char's of two
file names in the same folder are equal. To learn how they fix this problem, consider that
we like a batch file to do an operation on the two files:
"ComputerHelp.txt" and "ComputerInstructios.txt"
What we do is to pick the first 6 char's of the two names and add "~1" to the first and "~2"
to the second. So the two names become "comput~1" and "comput~2".
File names which contain spaces, like "Program Files" must be shortened using this formula
since batch files do not recognize a space within a name when they perform most operations.
However, they seem to recognize them when they do some operations, like:
'@set prg=c:\Program Files'
The names which we have used in the pathes list above are:
progra~1 meaning 'Program Files', refere~1 meaning 'Reference Assemblies' and tablet~1 meaning
'Tablet PC'.
Remember that at your computer, they may not be the first in their directories, so the number
'1' in their names may need to be changed to a different number.
The batch file normally displays each line before executing it. Preceding a line with '@'
prevents its display.
Adding to the refs.txt file:
----------------------------
The assemblies included into the file are the ones which are used by PC# classes only. If you
like to add to your classes a code which requires additional .NET assemblies, you need to add
those assemblies' dll file pathes to the file.
Also, you may like to download and use additional Microsoft software like "DirectX" or any third
party software. In this case, you need to add more assembly locations into the file. For example,
Directx would require several additions, some of them could be:
C:\WINDOWS\Microsoft.NET\Direct~1\1.0.2902.0\Microsoft.DirectX.dll
C:\WINDOWS\Microsoft.NET\Direct~1\1.0.2902.0\Microsoft.DirectX.Direct3D.dll
C:\WINDOWS\Microsoft.NET\Direct~1\1.0.2902.0\Microsoft.DirectX.DirectInput.dll
================================================================================================
The SDKVars.bat file
====================
When this file runs, it modifies the PATH environment variable in order to make the .NET SDK
accessable. You have no need to run it. Our tools will automatically run it whenever necessary.
During the startup, the version of this file which fits the '.NET' version you have downloaded
has been automatically generated for you and placed at your working directory.
So, you already have this file. However we are going to add here a version of this file which can
work with versions 2, 3.5 and 4 of the .NET Framework. You do not need it, but it should be good
to look at it. It may need to be modified to fit your .NET installation.
@Set NetPath=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
@if %1==2 (Set SamplePath=C:\Program Files\Microsoft.Net\SDK\v2.0)
@if %1==3 (Set SamplePath=C:\Program Files\Microsoft SDKs\Windows\v6.1)
@if %1==4 (Set SamplePath=C:\Program Files\Microsoft SDKs\Windows\v7.1)
@Set Path=%NetPath%;%SamplePath%;%SamplePath%\\Bin;%PATH%"
@Set LIB=%SamplePath%\Lib;%LIB%
@Set INCLUDE=%SamplePath%\include;%INCLUDE%
================================================================================================
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 the tool you used.
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 devices 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
keyname of the control which has generated the event assigned to (cs)
Method update should contain what you like to do when each event occurs.
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 BLOCK JUMP:
===============
Block jumps can be forward or backward. Their destination must be the start of a block within
method run() although the source of the jump does not have to be in method run(). This
means that you can start a jump from any location within method run(), method update or any
other method, but the destination should always be the start of a block within method run.
A jump call must be followed with (return;) since it must be the last statement to be executed
in the method which has generated the jump.
CALLING PC# PUBLIC METHODS:
===========================
All PC# methods require a mode string of upto 3 characters. There are two ways to supply the
mode string to the method:
(1) Assign the mode string to the method directly in this manner : gm("crd");
(2) Assign the mode string to (ls) and call the method in this manner: ls="crd";gm();
-------------------------------------------------------------------------------------------
THE FORM SIZE:
==============
It is important to know the terms involved in setting form's size since they may be confusing.
There are three sizes defined:
(a) The Form's Size:
--------------------
When you set the size of the form using method dm("s") or cm("fs"), you supply the desired
width and height assigned to (j,k) These two values set the external form's dimensions. This is
what we call the "Form's Size".
Method dm("s") is called from method init() before class (pcs) is initialized. If you call it,
class (pcs) will set the form size at the size which you have requested. Otherwise, it will set
it at PC#'s default size. This default size means that the width should be equal to the full
screen width of your computer and the height should be 400 Pixels. If your display resolution was
set at 800, this size would be (800,400) pixels.
After the initialization stage, you can change the Form's size using cm("fs") as many times as
you like. If you intend to use the Text Screen and like to set its size, you must use dm("s")
since the Text Screen is created during the initialization of class (pcs)
If you have changed the default size and like to return it back, call cm("fsd") and if you like
to make the Form equal in size to full screen size call cm("fsf") If you like the width and
height values assigned to (j,k) when you call method cm("fs") to set the ClientSize instead of
the Form Size, supply (ib=true)
At any moment, you can obtain the current Form's width and height with:
FormWidth = this.Width; and FormHeight = this.Height
(b) The Form's ClientSize:
--------------------------
The form comes with 4 margins. A top margin of 23 Pixels and a left, right and bottom margins of
4 pixels each. The Client size is the useable size of the Form which is equal to the Form size
less the area occupied by all the four margins.
Therefore, if the Form's size was the PC#'s default size stated in (a), its client size would be:
ClientSize Width = 800-(4+4) = 792 Pixels.
ClientSize Height= 400-(23+4) = 373 Pixels.
At any moment, you can obtain the current Form's ClientSize width and ClientSize height with:
cm("fwc");ClientWidth = of; and cm("fhc");ClientHeight = of;
(c) The Full Screen Form Size and ClientSize:
---------------------------------------------
When the user maximizes the Form, the Form fills the screen. The Form's width and height grow to
their highest possible values.
If the Form's size was the PC#'s default size stated in (a), the "Form Width" should remain the
same since it was the full screen width to start with. It's "Form Height" will most likely grow
to 574 pixels and its "ClientSize Height" will become:
ClientSize Height= 574-(23+4) = 547 Pixels.
At any moment, you can obtain the Full Screen Width and Full Screen Height with:
cm("fws");ScreenWidth = of; and cm("fhs");ScreenHeight = of;
Sizing the Default Bitmap (bio):
--------------------------------
The default bitmap object should always be equal in size to the ClientSize of the regular Form
(not the maximized form) unless scrollbars are installed.
This means that when the default form size is set during initialization, (bio) is created with a
size of (792,373) assuming that the display resolution is set at 800. It also means that whenever
you resize the Form using cm("fs"), (bio) is resized accordingly.
Whenever you like to have a drawing surface which exceeds the Form's client size, you need to
install scrollbars. You dtermine the width and height of the necessary (bio), and call methods
cm("fbh") and cm("fbv") to install the horizontal and vertical bars and create a new (bio) of the
required size at the same time.
PC# simplification of mouse event handling:
===========================================
When you write your code, you know only the Form size which you have selected or the PC# default
size if you have made no selection. The locations of your drawings are made relative to the
center of the default bitmap object (bio) If you have some drawings which you like to display
independantly from (bio) (See Example 12 - Handling Controls), you set their locations relative
to the center of the present bitmap object (bip)
When the user clicks at a specific point on the Form, you know which object he or she has clicked
at and set your event handling code accordingly. Normally, if your class is not extending (pcs)
and this was all you have done, your software will run fine as long as the user keeps the form at
its original size and keeps the scrollbars at their zero positions. Practically, the user may do
one or more of the following:
(1) Maximizes the form.
(2) Reduces or expands form size horizontally and/or vertically by dragging its top, bottom,
left side and/or right side.
(3) Changes positions of the scrollbars.
When this is done, your code will fail unless you have made an adjustment for all these Form
resizing and repositioning possibilities.
PC# has done this job for you. So, if your class extends class (pcs), write your code as if the
Form will always stay at original size and position and always start your mouse event handling
section in method update() with one of these two method calls:
gm("brc"); // Adjust mouse coordinates to make them relative to the center of original (bio)
gm("bdc"); // Adjust mouse coordinates to make them relative to the center of original (bip)
You use method gm("bdc") when the object to be clicked on is part of (bip) and made to be
scrollbar independant using method gm("bdf") or gm ("bdd")
You use method gm("brc") when the object to be clicked on is either drawn on (bio) or drawn on
(bip) and allowed to scroll with (bio) using method gm("bd")
The mouse coordinates come assigned to (oxf,oyf), the two methods receive them, modify them and
return them also assigned to (oxf,oyf)
PC# simplification of keyboard event handling:
==============================================
When method update() is called after a key has been pressed, it receives two parameters, (oc)
and (ob) The type char variable (oc) can be assigned either an ordinary ASCII character or a
code which represents a special function key.
The boolean variable (ob) is a flag which tells which character type (oc) contains. If (ob=false)
the character in (oc) is a standard ASCII char. If (ob=true) the character in (oc) is a special
function key code.
Standard ASCII characters:
--------------------------
We mean by standard ASCII character any alphanumeric char. It can be lower cased or upper cased.
It can contain non-printable char's with ASCII codes in the range (0:31) like the [TAB],
[BACKSPACE] and [ESCAPE] whose ASCII codes (in order) are 9,8 and 27.
Additionally, when the [Control] key is pressed in addition to any alphabetic char, (oc) receives
a character with ASCII code in the range (1:26)
Special function key codes:
---------------------------
These codes are assigned to (oc) whenever one of the special function keys is pressed. They are
as follows:
---------------------------------------------------------------------------------------------
Arrow Keys : l = Left Arrow r = Right Arrow u = Up Arrow d: Down Arrow.
Insert/Delete: i = Insert key e = Delete key
Lock Keys : c = Caps Lock n = Numeric Lock s = Scroll Lock
Page Up/Down : U = Page Up D = Page Down
Restart/Exit : B = Break H = Home
Other Keys : a = Alt h = help p = Print Screen
Function Keys: 1 = F1 2 = F2 3 = F3 4 = F4 5 = F5
6 = F6 7 = F7 8 = F8 9 = F9 0 = F10
----------------------------------------------------------------------------------------------
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 Keyboard. 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()
(3) The web screen. To indicate that the "web screen" is your text input device include
the statement (tia="w";) into method init()
(4) 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 the keyboard has been 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 Console. 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) The web screen. To indicate that the "web screen" is your text output device include
the statement (toa="w";) into method init()
(4) 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. It can also display pictures. At the bottom, it
contains a text field into which the user enters his response whenever your program
instructs him/her 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 color 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. It can also edit the text programmatically.
The Text Screen also accepts dynamically generated drawings.
Text Screen size is equal to Form's client size. Since the Text Screen is set during
initialization, you can set its size at method init() using dm("s")
The Web Screen:
---------------
The web screen has been developed mainly for networking. It looks mostly like the text screen
except that it executes and displays HTML instead of displaying plain text. Additionally, the
web screen contains a one line plain text display box to display instructions to the user and
a text field to receive user's reponse. Those two controls are used identically to the rich text
box and the text field of the Text Screen. Same commands are used.
WebScreen size can be set similarly to TextScreen.
To learn more about the Web Screen, see "Examples on Networking".
Example to show how to display a picture on the Text Screen:
------------------------------------------------------------
public class a:pcs {
public override void init() {
tia=toa="t"; // Use text screen for text input & output
base.init();
}
public override void run() {
os="";tm();tm();tm();tm(); // Move vertically to display position
os=" ";
tm("d"); // Move horizontally to display position
ims="images\\flower.jpg";tm("dg"); // Display picture
os="";tm(); // Move to next line.
}
}
Saving Text Screen's Rich Text into an RTF file and printing it (for PC# version 4.37 or later):
================================================================================================
The user can print the Text Screen's content using its menu. However, Wordpad is more capable of
doing this job . So, the better choice is to save the text into a Wordpad RTF file and to use
Wordpad for printing.
You can save the rich text of the Text Screen into a Wordpad RTF file using method tm("fsr")
The user can also do the same using Text Screen's menu.
Wordpad has all the means to print the file except that it has one problem. It does not allow
you to force the printer to move to a new page whenever you see that necessary. Personal C Sharp
has solved this problem for you.
insert the code << p>> within the RTF text where you want the printer to move to a new page,
save the modified file then call tm("FF") supplying it with that RTF file's name assigned to (fls)
The method will replace your codes with the necessary instructions to end the current page and
start a new one.
EXAMPLE:
--------
(1) Open Wordpad page, write the following 3 lines into it then save it into file "test.rtf" at
your working directory:
Line number 1.
<< p>>
Line number 2.
(2) Use Notepad to write class a which contains the following code:
public class a : pcs {
public override void run() {
cm("fe"); // Eliminate form
fls="test.rtf";tm("FF"); // Process formfeeds
}
}
(3) Save the class into file "a.cs" and run it with "pcpr a".
(4) Close Wordpad then start it again and open file "test.rtf". Notice that the code << p>> has
disappeared. It has been replaced with invisible characters.
(5) Print the file. It should print each line into a seperate page.
REMARK:
-------
The space between "<<" and the "p" in the code has been intentionally inserted in order to
prevent your browser from assuming that it's an HTML tag and cause a display problem.
DO NOT insert such space characters into the codes which you place into your text.
Example to show how to use System Console 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 GRAPHICAL OUTPUT DEVICE:
===========================
The graphical output device can be:
(1) The default Bitmap object (bio)
(2) The present Bitmap object (bip)
(3) A metafile which is currently open for writing.
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 a reference to its graphical
context, and this means that anything we draw is drawn on (bio)'s surface.
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")
Similarly, if your program includes an Image metafile which has been opened for writing, at
any time, you can set the metafile as the graphical output device by calling gm("sdm") Any
object drawn will then be automatically recorded into the file.
-------------------------------------------------------------------------------------------
STRING SEARCH:
==============
Method tm() at mode "s" performs a text search. The first step in searching a string
is to assign it to (txs) which the method searchs. Let us see how the search is done
in its general form:
BEFORE SEARCH: txs = xxxjsxxxjsxxxxxxxxxxxxksxxxx AFTER SEARCH: txs = ksxxxx
<--- os --->
The method can get for you the section of (txs) which is found between two strings
which you supply. You supply the two strings assigned to (js), (ks) and the string
returned to you comes assigned to (os). Then all chars of (txs) upto the end of (os)
are removed.
If (js) is found more than once, you assign to (j) the number of (js)'s which you
want to skip. In our example, j=2.
Let us see now how we can search a large size string in the real world to get a
particular piece of data:
(1) Locate the area where wanted data is, then look for any unique phrase which is
found before the data. Assign that phrase to (js) and nothing to (ks) then call
the method. This will remove everything upto the end of that phrase which brings
you closer to your data.
(2) Now assign few of the chars which are immediately before the wanted data to (js)
and assign few of the chars which are immediately after the wanted data to (ks)
and call the method again. This will return your wanted data assigned to (os).
Things may not go so smoothly. Let us see how we can overcome difficulties:
(a) Not every phrase within the text can be used for the search. If the text you are
searching was the HTML content of a web page and you like to be searching the
same text more than one time using the same program, you cannot use the HTML tags
for your search since they keep changing. The page may contain several ads which
also keep changing. You need to look for phrases which are guaranteed to be there
all the time. "Titles" are normally the best to use except that they are not many.
(b) In step (1) You may have not found any unique phrase. Every word you could find
has been repeated many times. To fix that, look for a phrase with as few
occurances as possible. Count the number of occurances and assign the number
to (j) before calling the method. This will eliminate everything upto the end
of the last phrase.
(c) Even that could be not easy to find sometimes. In this case do it in more than
one step. The phrase to assign to (js) in the first step could be far from the
wanted data and each time you repeat the procedure you get closer.
(d) Sometimes, you may prefer to remove a specific number of chars from (txs) instead
of specifying a phrase to skip upto. This may happen when you get too close to the
wanted data. You can do that with:
j=number of chars;js=ks="";tm("s");
--------------------------------------------------------------------------------------
CREATING SHORTCUTS:
===================
Method sm() can create a shortcut to any file on the desktop or into the start menu.
Assume that your working directory's path is "C:\\pcs" and it contains a file named
"test.txt". Here is a class which creates shortcuts to that file at both the desktop
and the start menu. The name we have selected for both shortcuts is "MyShortcut".
public class a : pcs {
public override void run() {
cm("fe"); // Eliminate form
fls="c:\\pcs\\test.txt";os="MyShortcut";sm("sc"); // Create shortcut at desktop
fls="c:\\pcs\\test.txt";os="MyShortcut";sm("scp"); // Create shortcut into start menu
}
}
--------------------------------------------------------------------------------------
DATE AND TIME
=============
Method sm() includes modes which can help you with obtaining current date and time and
performing date and time arithmatic operations. This method does numerous functions, so
let us carefully learn what it does.
The method expects input from you when you call it in addition to producing the output
which you want to get.
Method's Output:
----------------
The mode you call the method at sets the output which you require.
Here is a list of all the modes:
dd: Return date in the form mm/dd/yyyy
dt: Return time in the form hh:mm:ss
dw: Return Weekday (like Monday)
dm: Return Month name (like January)
dl: Return date in a long format (like Tuesday, September 5,2006)
In addition to that, you always get the resulting Present Date object assigned to (dtp)
Method's Input:
---------------
When you call the method, you should let it know which date object you want it to start
with. You may like it to do one of the following:
(1) Create a new object which represents current date and time. You can request this
option by supplying (os="")
(2) Create a new object which represents a different date and time. You can request this
option by supplying (os="mm/dd/yyyy") or (os="mm/dd/yyyy and js="hh:mm:ss")
(3) Work on the same object which has been created before. You can request this option
by supplying (ib=true)
Arithmatic Operations:
----------------------
After creating the object, sometimes, you only like to return the date or time in the
format which you have specified in the mode, some other times, you like to add or subtract
date or time components to/from the object before getting the result.
You assign the amount to be added to the date object to (ks) regardless to whether it is a
date or time component. The method will know which component it is by checking the seperator
used. A '/' seperator means date and a ':' seperator means time.
So if you supply (ks="0/12/0"), the method will know that you like to add 12 days to the
starting object and if you supply (ks="0:-2:120"), the method will know that you want to
subtract 2 minutes and add 120 seconds which will keep the time unchanged.
Adding (kb=true) means negate all 3 components in (ks), So if ks="01:30:20", it will be treated
as if it was "-01:-30:-20".
Examples:
---------
(1) os="";sm("dd"); // Get Present Date as "mm/dd/yyyy".
(2) ib=true;sm("dt"); // Get Time as hh:mm:ss" using object created in (1).
i=2000;um("s"); // Sleep 2 seconds.
(3) ib=true;sm("dt"); // Do the same 2 seconds later.
(4) ib=false;os="";sm("dt"); // Do the same using a new current date/time object.
(5) ib=true;ks="01:00:00";sm("dt"); // Add 1 hour to object created in (4).
(6) ib=true;ks="00:-3:00";sm("dt"); // Subtract 3 minutes from object created in (4).
(7) ib=true;ks="00:00:180";sm("dt"); // Add 180 seconds to object created in (4).
(8) ib=true;ks="01/01/01";sm("dd"); // Add 1 month, 1 day and 1 year to object.
(9) ib=false;os="01/01/1800";sm("dw"); // Obtain weekday of 01/01/1800.
(10)ib=true;sm("dl"); // Obtain Long Date format for same date.
And here are the results of running the examples:
(1) Getting Present Date and Time:...................09/05/2006
(2) Getting Time using object created in (1):....... 15:42:50
(3) Doing same over 2 seconds later:................ 15:42:50
(4) Doing same using new object:.................... 15:42:52
(5) Adding 1 hour to object created in (4):......... 16:42:52
(6) Subtracting 3 minutes from object created in (4):16:39:52
(7) Adding 180 seconds to object created in (4):.... 16:42:52
(8) Adding 1 month, 1 day and 1 year to object:..... 10/06/2007
(9) Obtaining weekday of 01/01/1800: ............... Wednesday
(10) Obtaining Long Date for same date: Wednesday, January 01, 1800
REMARK: The date and the time strings which you get from modes "dd" and mode "dt" are
uniform. Each component must be made of 2 digits except the year component which must
be made of 4 digits.
The date or time strings which you assign to (ks) to add to the object are not uniform.
Each component can be made of any number of digits and could be signed or unsigned.
--------------------------------------------------------------------------------------
Personal C# Timer:
==================
This timer is available in method um() at mode "t" of both classes, pcs and pasp. A JavaScript
version is also available. Operation is identical for all versions.
The timer counts time in milliseconds. It counts upto one minute (60,000 milliseconds) then
it resets back to zero. The time count is returned into (o). Each time you call the method,
it returns to you the amount of time which has passed since a reference time. You can make
the time the call is received a new reference time by supplying (ib=true) to the method.
Let us have some examples to clear things up.
(1) Assume that at one moment um("t") received this call:
ib=true;um("t"); It will use this moment's time as a reference for future calls.
(2) One second later it received this call:
um("t"); It will return (o=1000) since 1000 ms has passed since ref. time.
(3) One second later it received this call:
ib=true;um("t"); It will replace old ref with this moment's time.
(4) One second later it received this call:
um("t"); It will return (o=1000) since the new ref will be used.
In other words, the time the method returns assigned to (o) is the time elapsed since last
call when (ib) was true.
---------------------------------------------------------------------------------------------
Ranking:
========
Method um("R") ranks the data stored into array OD[]. It ranks the data in an ascending or
descending order depending on the value of (ib) which you supply. This method requires also
(oi) containing the total number of active rows in array OD[] which are to be sorted. This
is because array OD[] may contain some rows which are assigned zeros at its end which are not
part of the data.
To understand how it works, let us assume that the data was the result of a horse race. Before
the race, the race track prepares a list of the horses entering the race which contains their
names and the serial numbers assigned to them. After the race, the time in minutes which each
horse has taken to finish the race is added to the list. The list looks like this:
HORSE NO. HORSE NAME TIME TO FINISH
========= ========== ==============
0 Optimizer 4.24
1 Bluff 5.12
2 Nehro 2.90
3 Frosted 3.32
The winner is the fastest horse. So ranking the horses requires sorting the "Time to finish"
column in an ascending order which brings the result [2.90,3.32,4.24,5.12] This means that the
horses ranked list (by numbers) is [2,3,0,1] and (by names) is [Nehro,Frosted,Optimizer,Bluff].
To do this job programmatically, we use two arrays one "string" array which contains the
horse names and one "double" array for the times. Both arrays should be ordered by the horse
numbers. Let us use OS[] and OD[] for the two jobs. Method um("R") will be called with
(ib=false) to use ascending order. The method will return array O[] containing the horse
rankings by numbers. So it's contents are expected to be [2,3,0,1].
------------------------------------------------------------------------------
public class a:pcs {
public override void run() {
cm("fe"); // Eliminate Form
OS=new string[] {"Optimizer","Bluff","Nehro","Frosted"};
OD=new double[] {4.24,5.12,2.90,3.32}; // load arrays with data
oi=4;um("R"); // Rank OD[] at ascending order
//---- Ranking horses by names ----
for(c=0;c< O.Length;c++) { // Scan the "ranking by number" list
os=OS[O[c]];tm(); // Display each horse name at
} // same order as in the list.
}
}
------------------------------------------------------------------------------
The default size of array OD[] and all the other GUV Arrays is 500 rows. However you
can change their sizes by any amount using method dm("hg") Data in array OD[] can be
positive or negative and may contain any fractions.
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 multi-value
variable names like names of arrays, collections and hashtables are made of
"upper case" chars. There are no names which contain a mix of lower case and
upper case chars. As an example, (cls) is a string variable which represents
a color code, while (CLS) can be an array of color codes.
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 om("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 definintions:
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;
NEW: Starting with version 1.803, the new output variables of type "float" (oxf,oyf)
have been added. They'll be used to output mouse pointer coordinates and similar
values which require (x,y) numbers.
You may have noticed that (is) and (if) have been replaced with (ls) and (lf).
This is because "is" and "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 assignment 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 neglected all other variables. This was because we can guarantee that all the
variables which we have not assigned values to are assigned zeros.
REMARK: The GUV's (ic, jc, kc, ls) are used internally in processing your method calls. This
is why you don't see them among the parameters necessary for any method at any mode. However
they are treated like any other GUV's. This means that they are reset before the start of
your program and at the end of any method's execution.
In some situations, you may like to reset the GUV's by yourself either for real need or just
to be sure they are reset. Here are the methods which you can call for this purpose:
um("c") : Clear (reset) i, j and k based single-value GUV's.
um("co"): Clear contents of all (o) based single-value variable.
um("C") : Clear i, j and k based GU Arrays.
um("CO"): Clear contents of all (o) based Arrays.
cm("ir"): Reset all variables used as input parameters for cm("i")
wm("ir"): Reset all variables used as input parameters for wm("i")
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"). The default values are (guh=500) and (bch=5000)
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 "Control".
fs: Keyname for a "File".
ad: Rotation angle (in Graphics)
ds: Direction code.
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 objects, 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 brush object null gm("O");
rgp Present Radial gradient paint brush 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 class (pcs) 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 color 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 one. 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) 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 box: If you like the user to select the color, call
cm("dtc") in order to display the color dialog box and make (clp) a reference
to the selected color object (the method makes this assignment for you
after it receives user's selsection)
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 box 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.
** NEW ** USING REFLECTIVE COLORS:
----------------------------------
In addition to all the colors specified above, you can paint any shape object with
Gold or Chrome colors. See Example 9 of the chapter "Imaging" to know how.
SETTING THE FONT:
=================
--------------------------------------------------------------------------------------------
IMPORTANT REMARK:It seems that some of the fonts which have been available in older versions
of Windows and we have used in some of PC# examples are no longer free. The font "Edwardian
Script ITC" is one of them. So, if you find it in one example, replace it with another font
or purchase it from Microsoft at this site:
https://www.microsoft.com/typography/fonts/family.aspx?FID=110
--------------------------------------------------------------------------------------------
You may make your font setup simpler if you choose one of the following 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.
(4) Edwardian Script ITC and French Script MT: Beautiful fancy fonts which can be
used for special jobs, like creating greeting cards.
(5) Symbol: Roman letters.
(6) Webdings and Wingdings: Contains useful symbols and drawings.
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 es=Edwardian Script
fs=French Script sy=Symbol wb=Webdings wn=Wingdings
(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 box: If you like the user to select the font, call
cm("dtf") in order to display the font dialog box and make (fnp) a reference
to the selected font object (the method makes this assignment for you)
Example: cm("dtf");fns="o";
---------------------------------------------------------------------------------------------
WORKING WITH TEXT AND BINARY DATA:
==================================
Most of PC# methods which handle reading and writing of both text and binary data are made to
operate similarly.
When they read data, they return to you both (os) and OY[]. (os) contains the read data as text
and OY[] contains the read data as binary.
When they write data, they give you the choice to either write it in text [you assign the text
to (os)] or in binary [You assign binary data to OY[] and assign "@" to (os)].
Here are examples of methods which operate in this manner:
fm("R") & fm("W") Read all data of or write all data to a file.
nm("tr") & nm("tw") Read data from or write data to a tcp connection.
tm("Epe") & tm("Epd") Password-based Encryption and Decryption.
tm("Ese") & tm("Esd") Encrypt or Decrypt data using symmetric algorithm.
tm("Eae") & tm("Eae") Encrypt or Decrypt data using asymmetric algorithm.
tm("Eas") & tm("Eav") Digitally sign a document or Verify signature.
Additionally, all PC# servers' internal reading and writing methods operate in the same manner.
--------------------------------------------------------------------------------------------
WORKING WITH CONTROLS:
======================
You may use PC#'s methods to install controls, modify their initial setup parameters or obtain
their latest updated values. If you like to install additional controls without using PC#'s
methods, you can as long as you provide the delegates necessary for handling their events.
Additionally, if you like to do an operation on one of the PC# installed controls by yourself,
all you need to do is to call method cm("O") supplying the keyname of that control assigned
to (cs) The method will then make the present object for the type which the control belongs
to a reference to that particular control.
Example: If you like to do a special operation on the button (bt0) which PC# methods cannot
do, obtain a reference to that button by:
cs="bt0";cm("O");
Since it is a button the reference will be (btp) Using that reference you can do anything you
want to that object.
Present Object references for available controls:
-------------------------------------------------
btp Button lbp Label cbp CheckBox rbp RadioButton
chp ComboBox lsp ListBox tfp Text Field tap Text Area
rtp RichTextBox mmp MainMenu cmp Context Menu mip MenuItem
Control setup Parameters and update values:
-------------------------------------------
Method cm() at modes which start with "s" is used for setup. You supply it with the control's
keyname assigned to (cs) in addition to the required setup parameter(s). Some parameters are
common for all controls and some are special for specific ones.
Common setup modes:
-------------------
sC : Set color. The method receives a combined Foreground-Background color code assigned to
(cls) It can be made of either 4 characters or 6.
sF : Set Font. The method receives the font code assigned to (fns).
sB : Set Bounds. Sets the (x,y,width,height) at (j,k,i,o)
sA : Set Anchor at (cas) It can contain one or more of the direction codes (n/s/e/w)
sD : Set Dock at (cds) It can contain one of the direction codes (n/s/e/w) or cds="f":fill.
sx : Set focus at the control.
sE : Set Enable state. Receives (jb) and disables the control if (jb=true)
st : Set tool tip value. Assigns (cts) to the control's tooltip.
sg : Set background image. If ims="b". It makes (bip) the background Image; else it uses
the Image file name assigned to (ims)
sn : Set TAB order. It sets tab order at (id) If (id=-1) it skips the control.
sm : Attach context menu. The value assigned to (cs) should be "mnd0" where 'd'=group no.
Special setup modes:
--------------------
BUTTON:
l: Set Botton's label at (cis)
a: Set alignment as per (os) value which can be: c/e/w/n/s/ne/nw/se/sw.
u: Click the button programmatically.
LABEL:
l: Set Label control's text at (cis)
a: Set alignment as per (os) value which can be: c/e/w/n/s/ne/nw/se/sw.
CHECK BOX:
l: Set CheckBox control's text at (cis)
a: Set alignment as per (os) value which can be: c/e/w/n/s/ne/nw/se/sw.
u: Set CheckBox's state according to (cus) cus="1" means checked.
RADIO BUTTON:
l: Set RadioButton control's text at (cis)
a: Set alignment as per (os) value which can be: c/e/w/n/s/ne/nw/se/sw.
u: Set RadioButton's state according to (cus) cus="1" mean checked.
COMBO BOX:
u: Set ComboBox default text or selexted index. You should either supply default text
assigned to (cus) or keep (cus) empty and assign the index of the item to be selected
by default to (cui)
L: Set labels. Assign text of all items to CIS[] before calling this mode.
LIST BOX: At this mode the ListBox is checked to see if it is of Single Selection type
or of Multiple selection type before proceeding with setup.
u: If Single selection list, The item whose index is in (cui) will be the selected one.
If multiple selection list, CUS[] rows will be checked. When "1" is found to be the value
of a row, the list item with the same index as that row will be checked.
l: Set list title's label at (cis)
L: Set labels. Assign text of all items to CIS[] before calling this mode.
b: Set list type according to (ib) If (ib=true) it will become a "Multiple Item List".
TEXT FIELD: This is a single line TextBox.
u: Set Text Field's default text at (cus)
b: Set Boolean flag (ib) If (ib=true) make it a "Password" TextBox where characters are
displayed as astrisks.
e: Set editability according to (ob) If (ob=true) make it a "Read Only" TextBox".
s: Set Size. Sets the max number of char's it can take to (od)
TEXT AREA: This is a multiple line TextBox.
u: Set Text Area's default text at (cus)
e: Set editability according to (ob) If (ob=true) make it a "Read Only" TextBox".
s: Set Size. Sets the max number of char's it can take to (od)
RICH TEXT BOX:
u: Set Rich Text Box's default text at (cus)
e: Set editability according to (ob) If (ob=true) make it a "Read Only" RichTextBox".
MENU:
L; Add menu items to menu. Assign all Menu Item text to CIS[] before calling this mode.
---------------------------------------------------------------------------------------------
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
literal 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 */) and attempting to recompile it to see if the error persists.
(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 occurs, PC#
catches it, assigns the Exception object to (exp) then throw it back to your program, so
you can catch it and handle 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 occur. 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 occurs 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 occur. 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.
=========================================================================================
COMMENTING
==========
Commenting your program means to Personal C Sharp more than just explaining what it contains.
It means a full translation of your code in addition to dividing your code into paragraphs and
titled sections that simplifies its understanding. We have set some rules for commenting which
we'll explain here.
The C# language allows two methods of commenting:
(1) Preceding the comment line with "//".
(2) Inserting the comment text between "/*" and "*/".
We use only the first method for commenting and leave the second one for debugging.
Breaking a computer program into individual components:
=======================================================
We use the same logic which is used in book writing. Computer programming is a new technology
while book writing is an old one. Book writers have been working on improving books readability
over thousands of years, so why should'nt we make use of their lengthy and hard work to improve the
readability of our code? A book is made of:
(1) Words seperated with spaces.
(2) Sentences made of groups of words.
(3) Paragraphs made of groups of sentences and seperated from each others with blank lines.
(4) Titled sections made of several paragraphs.
(5) Chapters made of several titled sections.
Similarly a computer program is made of:
(1) Statements seperated with semi-colons like (lf=100;)
(2) Sentences. A sentence is a group of statements which together perform a small task.
For example:
lf=100;of=100;gm("crd"); // Draw a square of 100 X 100 Pixels.
We normally like each sentence to be on a seperate line occupying half of the line and
its description occupying the other half. We may include more than one sentence on a
single line if we find that it makes the description easier to understand.
(3) Paragraphs. A paragraph is a group of sentences which perform a larger task together.
Paragraphs are seperated with blank lines. They can start with one or more lines of
comments whenever necessary. Here is an example:
// To draw a square in black color at the center, you need to prepare a black pen first
// then assign wanted width and height to (lf,of) before calling gm("crd") to draw it.
cls="S9";gm("sps"); // Prepare a solid black pen.
lf=100;of=100;gm("crd"); // Draw a square of 100 X 100 Pixels.
(4) Titled sections. A titled section is made of a group of paragraphs which perform a larger
operation together. It can also start with one or more comment lines. We normally add
dashed lines around the section title as follows:
//--------------------------- Drawing the objects -----------------------------
// In this section a square will be drawn at the center of the form and a text
// line will follow the drawing.
(5) If it makes sense to divide your program further into chapters which are made of several
titled sections use equal signs to identify the chapter titles as follows:
//============================= GENERAL METHODS ================================
Chapters are necessary only for large size programs. Classes (pcs) and (pasp) which make
the entire Personal C Sharp software are divided into chapters. For example class (pasp)
is made of the following chapters:
1. Variable Declarations.
2. Initialization.
3. Text.
4. General Methods.
5. Graphics.
6. Web Developing.
7. Filing.
8. Networking.
Both classes are commented using the same method recommended above. Here is a sample
from class (pasp) which shows how method calls are processed. Method dm() is used for
the demonstration:
//================================== General Methods ====================================
//------------------------------------ dm() ---------------------------------------
public void dm() {
// SETTING DEFAULTS Normally, this method is called from within method init()
mts="d";mStart(); // Call mstart() with this method's name
if (eri>1 && mts.Equals("d")) dmEr(); // If eri>1 and not intra-method call, run
// PC# error detection for this method.
if (scb) {cln();return;} // If security disallows method, exit.
try {
switch (ic) {
case 'h': // HIGHEST EXPECTED NUMBERS: These variables are used to dimension arrays
// For example, if (flh=100), the max number of files which can be opened
// in the class is 100. This is because filing archives created can only
// hold 100 items. There is a default value for each variable.
// IN: o=New assignment for the variable. If (o=0) Restore default.
if (jc=='g') { // General use arrays
if (o==0) guh=500; // If (o=0) restore default
else guh=o; // Else set (guh=o)
}
else if (jc=='b') { // Used to dimension byte and char arrays only
if (o==0) bch=5000;else bch=o;
}
else if (jc=='t') { // For Thread groups
if (o==0) thh=0;else thh=o;
}
else if (jc=='c') { // For Controls
if (o==0) cmh=100;else cmh=o;
}
else if (jc=='f') { // For Files
if (o==0) flh=100;else flh=o;
}
break;
case 'p': // COMMAND MODE PARAMETERS: First parameter (number zero) is the program
// file name.
string[] PRS=Environment.GetCommandLineArgs();
// Get all par's into PRS[]
if (jc=='c') { // Get parameter count. OUT: o=count
for (o=PRS.Length-1;o>-1;o--) if (PRS[o].Length!=0) break;
o=o+1; // Scan backward until 1st par encountered
} // then add 1 to get the count
else { // Get value of one par. IN:i=par index
// OUT: os=par value
os="";if (PRS.Length>i) os=PRS[i];
}
break;
default : break;
}
}
catch (Exception e) {
if(eri>0) { // If error handling not done by child class:
bk(); // Call break point display method
exs=e.Message;pr(exs); // Get exception message and display it
}
else { // Else:
exp=e; // Assign Exception object to (exp)
throw exp.InnerException; // Throw an exception to be caught by child
} // class
}
finally {mEnd();} // Call mEnd()
}
//------------------------------ dm() Error Handling ---------------------------------
private void dmEr() { // PC# Error handling for dm()
int i;string ms="",mss=""; // ms=Mode string alone mss=All valid modes
// Example: if mds=[tm("dl");] ms="dl"
i=mds.Length-7; // Length of mode string
ms=mds.Substring(4,i); // Get mode string
// ** Mode check // (mss) contains all method's valid modes
mss="hg hb ht hc hf p pc ";
if (mss.IndexOf(ms+" ")<0) ers="Unknown mode";
// report error if not valid mode
if (ers.Length>0) pr(ers); // If any error found display error message.
}
================================================================================================
Returning your computer to an older Restore Point:
==================================================
Since the beginning of Windows 10, Microsoft has been adding more and more security measures which
have caused some of Personal C Sharp methods to stop functioning properly. Here are some examples:
(1) Despite the fact that all our web examples have been developed purely with Microsoft's ASP.NET
and tested with several versions of the original Internet Explorer, some of our examples don't
run properly with the latest version of the Internet Explorer and some don't run at all with
Microsoft's Edge.
(2) Most of our Assembly Language examples have stopped running as they should.
(3) Examples on Networking have started to show problems also.
We know that you are not interested in hacking anybody. You are interested in writing software for
your own personal use. So, you need your software to work properly at least on your own computer.
One way to accomplish that would be by restoring your computer to an older restore point each time
you find a new problem.
If you don't know how to do so, follow these procedures:
--------------------------------------------------------
REMARK: This process may take more than one hour. You must not stop it after it starts. So we advise
you to wait for the time when you can afford keeping your computer unused for 2 hours before you do it.
We also advise you to close all active windows before you start.
(1) Open the "Control Panel". The easiest way is to ask Cortana to do it. Check the drop down list
named "View by" at top right corner. If was set at "Category", change its setting to "Small Icons".
(2) Click on the item "Recovery" then select "Open System Restore" and click on [Next].
(3) Select the item "Choose a different restore point" at the bottom and click on [Next].
(4) Select the item "Show more restore points" at the bottom to display all restore points available.
(5) Select the "restore point" date you want then click on [Next] then on [Finish].