Personal C Sharp         by    famsoft.org

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

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


EXAMPLE 9: Now we are going to see an example on drawing shadows and the use of
           Affine transform.
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    gm("dn");                              // Turn off auto-display
    //----------------------- Drawing a pattern on the background -----------------------
    cls="y0";gm("sps");                    // Set color to yellow.
    for(int i=-180;i<181;i+=4) {           // Fill drawing area with horizontal yellow
      kf=i;of=2;lf=360;gm("crf");          // lines, 2 pixels thick to use as background
    }
    xs="Windows.NET Programming At Its Best ";
    xs+=xs;                                // String to be drawn twice.
    //--------------------------- Drawing the string's shadow ---------------------------
    fns="crb24";                           // Set font to bold courier, size 24.
    lf=of=320;gm("bn");                    // Create 320 X 320 Bitmap.
    gm("sdb");                             // Set output device to (bip) to draw on it.
    cls="S92";gm("sps");                   // Set color to (20% opaque) black
    char[]XC=xs.ToCharArray();
    for (x=0;x<xs.Length;x++) {            // Scan arch string, assign its char's one by
      os=""+XC[x];                         // one to (os) then create (gpp) representing
      gm("ct");                            // the char.
       lf=150;of=180-5*x;kb=true;          // Modify (utp) to xfrm char's to points of
      ad=(90-5*x);                         // rad=150 and different angles starting at 180
      gm("stu");                           // and making a full circle.
      gm("gtf");                           // Xfrm & fill (gpp) of each char.
    }
    gm("sdd");                             // Return output device to its default setting.
    k=2;gm("bb");                          // Blurr (bic) to make it look like a shadow.
    jf=0;kf=-10;gm("br");                  // Draw the bitmap with the shadow on it off
                                           // center by 10 pixels (down)
    //------------------------------- Drawing the string --------------------------------
    cls="b0";gm("sps");                    // Set color to pure blue
    for (x=0;x<xs.Length;x++) {            // Draw the same circle of chars directly on
      os=""+XC[x];                         // the default graphical output device,
      gm("ct");                            // exactly at its center
       lf=150;of=180-5*x;kb=true;
      ad=90-5*x;
      gm("stu");
      gm("gtf");
    }
    //-------------------------- Drawing the large "PC#" shadow -------------------------
    gm("stu");                             // Reset (utp)
    fns="trb84";                           // Change font to a larger Times Roman font.
    lf=of=200;gm("bn");                    // Create 200 X 200 Bitmap object
    gm("sdb");                             // Set output device to (bip)
    cls="S92";gm("sps");                   // Set Color to black with 20% opacity.
    os="PC#";gm("ctf");                    // Draw-fill the string on the bitmap.
    gm("sdd");                             // Return to default output device setting.
    k=3;gm("bb");                          // Blur the shadow on (bip).
    jf=0;kf=-15;gm("br");                  // Draw shadow shifted 15 pixels down.
    //--------------------------- Drawing the large "PC#" body --------------------------
    os="PC#";gm("ct");                     // Create text object
    cls="y39o09";id=10;                    // cls=brightest-darkest colors, depth=10
    ad=60;ks="d";gm("grs");                // Shear angle=60,render with sp effects-depth
    gm("d");                               // Display graphics.
  }
}
=========================================================================================
TUTORIAL:
Why have we turned auto-display off?
The program runs slow and flickers a lot, so it seemed to be more covenient to keep
display off until the drawing is complete.
Why did we need the yellow background pattern?
To improve shadows' look. There are three factors which make Shadows look real:
(1) Drawing something rough on the background.
(2) Drawing them in partially transparent gray color.
(3) Blurring them.
AFFINE TRANSFORM:
Affine transform is a mapping between the current coordinate system and a new coordinate
system which you like to switch to.  It can be represented by a matrix which contains the
scaling, shearing and translation parameters.
The order of operations is important.  For example, rotating an object around  form's
center then moving it to a new location is not the same as if you move the object first
then rotate it.
With PC# you need not to worry.  You call method gm("stu") or gm("stp") with all the
parameters at once and  everything will be done at the right order. Mode "stu" is for
"unit transform setup" which is a general Affine transform for shapes, bitmaps, brushes,
etc. Mode "stp" is for the printer.
Affine transform parameters:
jf,kf      The original coordinates of object's center relative to form's center (before
           the transform is applied to the object)  If you create all your objects
           centered at Form's center, you'll have no need to assign values to jf,kf.
lf,of      The (x,y) displacements of the object.  In case the original object center
           was at (0,0), (lf,of) simply mean the new location of the object center.
jd,kd      The scale factors. If equal to (2,0.5), the object will be enlarged to double
           the size horizontally and reduced to half the size vertically.  If either
           value is negative, the object will be inverted.  For example (jd=-1) produces a
           mirror image of the original object with the vertical axis acting as the mirror.
id,od      The shear factors. The effects of shearing have been discussed before.
ad         The rotation angle in degrees.  You need to understand that the rotation is
           going to be around object's center which is point (jf,kf) not around form's
           center.
ob         Normal order concatenation.  Setting (ob=true) means that you like to
           concatenate the transform you are setting to the original transform with
           the original one applied first. Note: if both (ib,ob) are set to false, the
           new transform will replace the original one.
ib         Reverse order concatenation.  Setting (ib=true) means that you like to
           concatenate the transform you are setting to the original transform with
           the original one applied last. Note: if both (ib,ob) are set to false, the
           new transform will replace the original one.
Transformation order:
As stated before, PC# takes care of applying each of the required transformations at the
correct order.  However, if you are concatenating transforms, you need to care about the
concatenation order.  Assuming you are interested in scaling shearing and/or rotating
objects around their centers then displacing their center to a new location, you should
keep the following order:   Scale - Shear - Rotate - Translate.
=========================================================================================
 

demo29.jpg

              Example 9: Shows how to use shadows to add 3D look to your drawings
You may download the executable file for Example 9 at: http://mysite.verizon.net/vze1l4h6/examples/D9.exe

EXAMPLE 10: This example shows how to make the object you are drawing looks elevated up
            or down.
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    //-------------------- Painting background --------------------------
    cm("fwc");float wf=of;                 // Get Form's Client width and height,
    cm("fhc");float hf=of;                 // Store them for future use
    cls="s4";gm("sps");                    // Prepare light gray paint
    lf=wf;of=hf;gm("crf");                 // Fill form's background with it
    xs="Personal C Sharp";                 // Prepare string to be drawn
    fns="trb84";                           // Set font to TimesRoman, bold, 84
    //-------------------- "Elevated up" String --------------------------
    y=40;                                  // Vert pos where String is to be drawn
    cls="s9";gm("sps");                    // Set color to white
    os=xs;kf=y+2;gm("ctf");                // Draw text slightly above (y)
    cls="S9";gm("sps");                    // Set color to black
    os=xs;kf=y-2;gm("ctf");                // Draw text slightly under (y)
    cls="s4";gm("sps");                    // Set color to wanted foreground color
    os=xs;kf=y;gm("ctf");                  // Draw text exactly at (y)
    //-------------------- "Elevated down" String --------------------------
    y=-40;                                 // Vert pos where String is to be drawn
    cls="S9";gm("sps");                    // Set color to black
    os=xs;kf=y+2;gm("ctf");                // Draw text slightly above (y)
    cls="s9";gm("sps");                    // Set color to white
    os=xs;kf=y-2;gm("ctf");                // Draw text slightly under (y)
    cls="s4";gm("sps");                    // Set color to wanted foreground color
    os=xs;kf=y;gm("ctf");                  // Draw text exactly at (y)  }
}
=========================================================================================
TUTORIAL:
Easy example. All we needed to do, was to display the string 3 times one time in black
color, on time in white color and one time in the wanted color between the first two.
The white colored string looks like a reflection and the black colored string looks like
a shadow. Since we normally expect the light source to be at the top, when we see a
shadow at the bottom side of the object, we feel that the object is elevated up and when
we see the shadow at the top side, we feel that the object is elevated down.
=========================================================================================

demo30.jpg

          Example 10: Demonstrates another method for giving the 3D look to your Drawings
You may download the executable file for Example 10 at: http://mysite.verizon.net/vze1l4h6/examples/D10.exe

EXAMPLE 11: Now, let us see how we can save our drawing into file. We are going to save
            the piece of jewelry created in example 8 into a "jpeg" format file named
            "x.jpg".
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    j=k=200;cm("fs");                      // Resize form to fit object
    cls="s5";gm("sps");                    // Prepare light gray paint
    lf=of=200;gm("crf");                   // Fill form's background with it.
    //------------------------- Drawing the object -------------------------
    lf=of=170;gm("ce");                    // Create the circular gold plate
    cls="o5y5";gm("spl");                  // Prepare linear gradient brush for it
    gm("grf");                             // then render-fill the gold plate.
    lf=6;of=50;gm("c=");                   // Create hexagon shape object at center.
    cls="r0";ks="r";gm("grs");             // Draw the object using sp effects-refl at
    jf=45;cls="b0";ks="r";gm("grs");       // center in red, then repeat 6 times using
    jf=-45;cls="b0";ks="r";gm("grs");      // different colors and different locations
    jf=22;kf=40;cls="g0";ks="r";gm("grs");
    jf=-22;kf=40;cls="m0";ks="r";gm("grs");
    jf=22;kf=-40;cls="m0";ks="r";gm("grs");
    jf=-22;kf=-40;cls="g0";ks="r";gm("grs");
    lf=of=25;gm("ce");                     // Create a circle at center (pearl)
    for (int x=0;x<20;x++) {               // Draw it 20 times using sp effects-reflection
      jf=80;kf=18*x;kb=true;               // at locations around the plate. Polar coord's
      cls="p0";ks="r";gm("grs");           // are used for specifying locations
    }
    //---------------------------- Saving (bio) ---------------------------
    bip=bio;fls="x.jpg";gm("bsj");         // Make (bip) refer to same object (bio) refers
                                           // to, then save it in "jpeg" format
  }
}
=========================================================================================
TUTORIAL:
The code remained the same, we have only added some code at the top to reduce form's
size (which automatically reduces the default graphical device bitmap (bio) to the same
new size. We have then painted the back ground of (bio) with light gray paint. After
drawing the object we saved it into a jpg file.
As you know (bio) is transparent, we depend on the Form underneath it in adding background
to our drawings. This works fine as long as we are only interested in drawing them to the
screen. If we want to save (bio), we must add the missing background.
The jpg format is great in memory saving. The bmp format uses a lot more memory but looks
better. Reducing form's size is essential in order to reduce the file size.
=========================================================================================

demo31.jpg

 Example 11: Saving your drawing to file
You may download the executable file for Example 11 at: http://mysite.verizon.net/vze1l4h6/examples/D11.exe

EXAMPLE 12: Now, let us read the file back and draw the image.
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    fls="x.jpg";gm("blf");                 // Create a new bitmap object and load the
                                           // file into it at full scale.
    gm("br");                              // Render (bip) to default graph. output device
  }
}
=========================================================================================
You may download the executable file for Example 12 http://mysite.verizon.net/vze1l4h6/examples/D12.exe

EXAMPLE 13: Let us now write a program to show how to handle a mixture of Controls and
drawings and how to make them control each others. We are going to create two combo boxes
and a button in between on the form. On the default graphical output bitmap (bio) above,
we are going to draw 4 different shapes. The user selects a shape and a color by the
combo boxes then click the button to start the execution. When this happens, the selected
shape will be filled with selected color.
Additionally, the jewel object which we have saved in a file will be used as the
background image for the button.
=========================================================================================
public class a : pcs {
  public override void init() {
    bli=1;                                 // Initialize at block 1
    base.init();
  }
  public override void setup() {
    cs="bt0";i=100;o=100;ims="x.jpg";cm("i");
                                           // Create bt0 with background image
    cs="ch0";cus="Select a Shape";j=-250;i=190;o=40;cls="b0s5";fns="trb16";
             CIS=new string[] {"Triangle","Square","Circle","Pentagon"};
             cm("i");                      // Combo box ch0 with choices of shapes
    cs="ch1";cus="Select a Color";j=250;i=190;o=40;cls="b0s5";fns="trb16";
             CIS=new string[] {"Red","Green","Blue","Black"};
             cm("i");                      // Combo box ch1 with choices of colors
  } 
  public override void update() {
    //  Var's: s=Shape object number
    //         c=Color order number
    if ("bt0".Equals(cs)) {                // if bt0 clicked
      cs="ch0";cm("gu");                   // Get ch0 update (selected index)
      s=cui;                               // Assign selectes shape index to (s)
      cs="ch1";cm("gu");//string text=cus; // Get ch1 update
      c=cui;                               // Assign selectes color index to (c)
      bli=2;um("b");                       // Goto block 2 for execution
    }
  }
  public override void run() {
    if (blp==1) {                          // Initialization block
      jf=-250;kf=90;lf=3;of=150;gm("c=d"); // Draw the triangle
      jf=250;kf=100;lf=of=120;gm("crd");   // Draw the square
      jf=-250;kf=-100;lf=of=130;gm("ced"); // Draw the circle
      jf=250;kf=-100;lf=5;of=150;gm("c=d");// Draw the pentagon
    }
    if (blp==2) {                          // Execution block
      cls="r0 g0 b0 S9 ".Substring(3*c,2); // Get (cls) for selected color
      gm("sps");                           // Create solid pen/brush for the color
      if (s==0) {                          // If item 0 was selected, draw-fill triangle
        jf=-250;kf=90;lf=3;of=150;gm("c=f");
      }
      else if (s==1) {                     // If item 1 was selected, draw-fill square
        jf=250;kf=100;lf=of=120;gm("crf");
      }
      else if (s==2) {                     // If item 2 was selected, draw-fill circle
        jf=-250;kf=-100;lf=of=130;gm("cef");
      }
      else if (s==3) {                     // If item 3 was selected, draw-fill pentagon
        jf=250;kf=-100;lf=5;of=150;gm("c=f");
      }
    }
  }
}
=========================================================================================
TUTORIAL:
This example opens the road for a new discussion. The controls and the drawings in the
example have been apart from each other, so there has been no visibility problem for
either one. What could happen if an object was drawn on the top of a control?
What we have is the form with all the controls installed into it, and a transparent
bitmap object above it containing the drawings. So, theoritically, the object drawn on the
bitmap should cover the control making it invisible. In reality, this is not allowed.
Although the object can hide the form's body, it cannot hide the controls it contains.
The only way you can prevent a control from showing through your object, is by making the
control invisible.
The "text screen" is made of controls which cover the entire form, so if you turn it on,
you'll have no chance to see any graphics. However, method tm() can make the text screen
temporarely invisible allowing graphics to appear. To allow graphics to be visible, call
tm("vg") To allow text to return back to visiblity call tm("vt")
=========================================================================================

demo32.jpg

                     Example 13: Shows how to handle a combination of controls and drawings
You may download the executable file for Example 13 at:http://mysite.verizon.net/vze1l4h6/examples/D13.exe


                                     PRINTING
                                    ==========
EXAMPLE 14: We like to do the following:
(a) Print a number of text lines on a page. Use the "Print setup" dialog to select the
number of copies to be printed.
(b) Display some text lines on the "text screen" then print them. Select the number of
copies programatically.
(c) Print a text file. Use the "Page Setup" dialog to select orientation manually.
(d) Create a bitmap object loading an image file into it then print it. Set the
orientation programatically in this case.
(e) Finally obtain the number of printable lines per page when a specific font is used.
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  public override void init() {
    tia=toa="t";                           // Select "text screen" display
    base.init();                           // Should be last statement in init()
  }
  public override void run() {
    //----------------------------- (a) Printing Text Lines -----------------------------
    gm("pn");                              // Initialize for a new "Print Document" job
    gm("psi");                             // Show Print Information Dialog
    OS[0]="Text Line 1";                   // Populate string array OS[] with
    OS[1]="Text Line 2";                   // two lines of text
    oi=2;                                  // Number of lines
    fns="trp12";gm("prt");                 // Print OS[]'s text using supplied font
    //-------------------------- (b) Printing Text Screen's Text -------------------------
    os="Text Line 1";tm();                 // Display tow lines of text
    os="Text Line 2";tm();                 // on the "text screen"
    gm("pn");                              // Initialize for a new "Print Document" job
    o=2;gm("psn");                         // Select "number of copies=2"
    tm("g");                               // Get text screen's text lines in (OS[]) and
                                           // number of lines in (oi)
    fns="crp14";gm("prt");                 // Print OS[]'s text using supplied font
    //----------------------------- (c) Printing a Text File -----------------------------
    gm("pn");                              // Initialize for a new "Print Document" job
    gm("psg");                             // Show Print Page Dialog
    fns="trp10";fls="x.txt";gm("prf");     // Print the file using supplied font
    //---------------------------- (d) Printing Bitmap Object ----------------------------
    tm("vg");                              // Change visibility from text to graphics
    fls="pix.jpg";gm("blf");               // Create new Bitmap & load image file into it
    gm("br");                              // Display the Bitmap object for inspection
    gm("pn");                              // Initialize for a new "Print Document" job
    ib=true;gm("psl");                     // Select "landscape" orientation.
    kf=200;gm("prb");                      // Print the Bitmap object with it's center
                                           // 2 inches above paper's center.
    //------------------------ (e) Obtaining Number Of Lines/Page ------------------------
    tm("vt");                              // Return visibility to text
    gm("pn");                              // Initialize for a new "Print Document" job
    fns="trb12";gm("pgt");                 // Get total number of lines/page
    os="Number of lines per page="+os;tm();// Display result.
  }
}
=========================================================================================
TUTORIAL: Here are few Remarks:
(1) Text printing starts at page's set margins horizontally and vertically. Bitmap
is done the ordinary PC#'s way; you supply the coordinates of the center of the Bitmap
object relative to page boundaries center measured in (1/100)th of an inch units and
assigned to (jf,kf) Page boundaries means page's surface area less left, right ,top and
bottom margins.
(2) Method tm() can print the "text screen" contents simply by calling tm("p") It allows
specifying the font to print with, but it does not allow special printer setups. This is
why we did not use it.
(3) As you must have noticed, all text is printed in black and with one font. If you like
to print your text with all the colors and fonts you like, display it on the "text screen"
first, save it to an "RTF" file using method tm("fsr") then print it using Microsoft's
"Word" or "WordPad".
(4) Whatever we have printed in this example was either text or graphics, what if you
like to print a combination of the two on one page. You know that you can create a Bitmap
object, set it to be the graphical output device and draw all the graphics and text you
want on it then print it. The only problem is the size.
Computer screens and print papers do not match in size. Standard paper size is 8.5" X 11"
which means that their height exceeds their width. For computer screens, the opposite is
true.
Fortunately, the use of the "default graphical output bitmap (bio)" has greatly
simplified this matter. We can set the width and height of (bio) to match the print
paper's width and height in proportionality, do all the drawing on it, then scale it to
paper boundaries size at the last moment as we print it.
Now, the question left to be answered is how large should (bio) be. Paper's surface is
normally larger than the screen's surface, so we expect to draw more on papers than we
can on the screen. So we need (bio) to be as large as possible, yet possible to be
displayed on the form. So this is what we need to do:
(a) Make the form's size as large as it can be which is full screen size.
(b) Choose (bio)'s width so it fills the form horizontally.
(c) Choose (bio)'s height so its width/height ratio matches paper's boundaries
    width/height ratio. We mean by "paper boundaries" paper's size less margins.
(d) We need to make it possible to view any part of (bio) on the screen.
The next example will show how to do that.
You may download the executable file for Example 14 at: http://mysite.verizon.net/vze1l4h6/examples/D14.exe

EXAMPLE 15: We are going to write a program to satisfy all the requirements listed above
and will use a button which acts as a "toggle switch", one click allows us to view the
upper section of (bio), the other click allows us to view the lower section.
We are going to populate (bio) with 12 images obtained from files flower1.jpg-flower12.jpg
and 3 lines of text. at the end we are going to save it into the "jpg" file "flowers.jpg"
and print it scaling it to full paper boundaries size.
=========================================================================================
public class a : pcs {                     // Always remember, class name = file name
  bool UpDown;                             // Declare a boolean type var named "UpDown"
                                           // UpDown=false means upper section on display
  public override void init() {
    base.init();
  }
  public override void setup() {
    // Var's used: b=Form's bottom line position where Button will be located.
    cm("fsf");                             // Make Form's Client Size=Full screen size
    cm("fhc");of=of/2;om("ff");om("ti");b=o;
                                           // Get new form's height, devide it by 2,
                                           // convert result to (int) & assign it to (b)
    um("co");                              // Reset all (o) base var's, so they cause no
                                           // problem when we use method cm()
    cs="bt0";cis="Frame Change";j=0;k=-b+40;i=100;o=40;cls="r0y0";cm("i");
  }                                        // Install a button slightly above bottom line
  public override void update() {
    if ("bt0".Equals(cs)) {                // if bt0 clicked
      if (UpDown) kf=0;else kf=-500;       // If lower section presently displayed set
                                           // kf=0 to display upper section else kf=-500
      UpDown=!UpDown;                      // then change UpDown flag state.
       gm("d");                            // Display (bio) at location (0,kf) of the Form
    }
  }
  public override void run() {
    // Var's used: w=Paper boundaries width
    //             h=Paper boundaries height
    //             x=Screen's width
    //             y=Screen's height
    gm("pn");                              // Initialize for a new "Print Document" job
    gm("pgw");om("ti");w=o;                // Get paper bound's width, convert to (int)
    gm("pgh");om("ti");h=o;                // Get paper bound's height, convert to (int)
    cm("fwc");om("ff");om("ti");x=o;       // Get screen width, convert to (int)
    of=x*h/w;om("ff");om("ti");y=o;        // Calculate how much screen height would be
                                           // to be proportional to paper.
    lf=x;of=y;gm("bn");                    // Create (bip) to fit these dimensions
    bio=bip;gm("sdd");                     // Make (bio) refer to same object and reset
                                           // as the Graphical output device
    gm("dn");                              // Stop auto-display. Display only with gm("d")
    cls="S9";gm("sps");                    // Create black color paint
    lf=x;of=y;gm("crf");                   // Paint entire form with it.
    cls="s9";gm("sps");                    // Create white color paint
    fns="trb32";                           // Select font
    kf=266;os="Flowers are Joyful!";gm("ctf");
    kf=0;os="Flowers are wonderful!";gm("ctf");
    kf=-266;os="Flowers are beautiful!";gm("ctf");
                                           // Display text at 3 different locations of bio
    for (y=0;y<4;y++) for (x=0;x<3;x++) {  // Read all 12 image files, use (utp) to move
      fls="c:\\cs\\images\\flower"+(x+1+3*y)+".jpg";gm("blf");
      lf=-275+275*x;of=400-266*y;gm("stu");// each of them at a specific location in (bio)
      gm("brt");                           // then render it there.
    }
    bip=bio;                               // Make (bip) refer to same object as (bio)
    fls="flowers.jpg";gm("bsj");           // Save the bip with all images and text it
    lf=w;of=h;gm("prb");                   // contains then print it after scaling it
  }                                        // to paper boundaries size.
}
=========================================================================================

demo33.jpg

demo34.jpg

Example 15: Shows how to create and print a large Bitmap object which contains enough graphics to fill an entire page.
You may download the executable file for Example 15 at: http://mysite.verizon.net/vze1l4h6/examples/D15.exe
You'll also need to download the 12 image files: http://mysite.verizon.net/vze1l4h6/examples/flower1.jpg