Personal C Sharp                                                         By  famsoft.org Home How To Start Examples-Desktop Examples-Web PC# Methods Reference-Desktop Reference-Web

EXAMPLE 2: If you are wondering why we need the polar coordinate system, some applications can be significantly simplified by using this system. Here is a figure which could be hard to draw using Cartesian coordinates. ========================================================================================= public class a : pcs { public override void init() { base.init(); } public override void run() { lf=of=200;gm("ced"); // Draw a circle, diam=200 pixels for (float a=0;a<360;a+=60) { // make a=angle values between 0,300 kb=true;jf=100;kf=a;lf=of=200; // using polar coord's draw arches with center jd=(double)a+120;kd=120; // at radius=100, angle=a, start angle=a+120 gm("cad"); // Extent angle=120 } } } =========================================================================================

TUTORIAL: What are we drawing on? ----------------------- What we have is the form surface on which we can install controls. We can also paint its background with any color or tile it with a background image. We can also draw on it except that we don't like to do so for a reason which we'll explain shortly. On top of the form is a transparent bitmap image which we draw on. Since the bitmap image is transparent, everything the form contains shows through it and combines with the drawings. In order to maximize simplicity, avoid some errors and insure that your program runs once only, we include all program code into method run() Whenever the Form's size is minimized, then restored back to original size, the .NET software redraws for us all controls and background paint or image on the form, but it does not redraw anything else which we could have drawn directly on the form using method run(). PC# redraws the bitmap image with all the drawings on its surface, so we get everything to show up again. A second advantage of using the bitmap image is that it allows us to save our drawings into a file with ease and reliability. We'll see an example on that shortly. One more advantage, is the compatibility between drawing on the form and drawing on client's browser which we'll see when we get into web developing. Finally, this way has simplified miximg class (pcs)'s drawings with class (pcs3)'s We'll see that when we get into the chapter of "Using the Windows Presentation Foundation". ========================================================================================= EXAMPLE 3: Now, we'll see a demonstration of what you can do with "Shear" and "Rotation". This is the easiest way to draw a diamond shaped object or a parallelogram. ========================================================================================= public class a : pcs { public override void init() { base.init(); } public override void run() { lf=260;of=100;id=-1;od=0;gm("crd"); // Draw a rect with horiz shear factor=-1 cls="b05";gm("sps"); // Create solid blue pen lf=of=60;ad=45;gm("crf"); // Create, fill a square, rotated 45 degrs cls="r0";gm("sps"); // Change color to red lf=of=200;id=0;od=-1;gm("ced"); // Draw a circle with vert shear factor=-1 } } ========================================================================================= TUTORIAL: Shear Factors (id,od): ---------------------- To learn the effect of shearing, assume we have a Rectangle and like to convert it into a Parallelogram by rotating and stretching either its vertical sides or its horizontal sides by an angle (a) The table below shows the possible assignments of the shear factors and the resulting Shape in each case: id od Transformation result ------ ------ ------------------------------------------------ tan(a) 0 The vertical sides rotate anti-clockwise by (a) -tan(a) 0 The vertical sides rotate clockwise by (a) 0 tan(a) The horizontal sides rotate clockwise by (a) 0 -tan(a) The horizontal sides rotate anti-clockwise by (a) A combination of shearing, and rotation can make you able to get the necessary parallelogram for your application. =========================================================================================

EXAMPLE 5: Drawing the diamond shape has been easy. How about drawing an "ace of hearts"? ========================================================================================= public class a : pcs { public override void init() { base.init(); } public override void run() { cls="S9";gm("sps"); // Set color to black. lf=224;of=300;gm("crd"); // Draw card outline rectangle cls="r0";gm("sps"); // Set color to pure red. fns="trp24"; // Set font:TimesRoman,plain, size=24 os="A";jf=-92;kf=135;gm("ctf"); // Draw the text "A" at top left corner os="A";jf=92;kf=-135;ad=180;gm("ctf"); // Draw same rotated 180 deg at bottom right createHeart(); // Run local method to create the heart (gpp) // It comes large in size, centered into form GraphicsPath gpp1=(GraphicsPath)gpp.Clone(); // Make a copy of (gpp) GraphicsPath gpp2=(GraphicsPath)gpp.Clone(); // Make a second copy of (gpp) //--------------------------- Drawing the center heart ------------------------------ jd=kd=0.125;kf=9;gm("stu"); // Create a unit Affine Transform to scale // (gpp) to 1/8th without location change gm("gtf"); // Xfrm then render-fill (gpp) //----------------------------- Drawing Corner hearts ------------------------------- gpp=gpp1; // Make (gpp) refer to 1st copy of object jd=kd=0.05;jf=-97;kf=123;gm("stu"); // Create Affine Xfrms to scale to 5% and move gm("gtf"); // it to corner then render & fill (gpp) gpp=gpp2; // Make (gpp) refer to 1st copy of object jd=kd=0.05;jf=88;kf=-109;ad=180;gm("stu"); gm("gtf"); // Do the same at other corner except that the } // Xform also rotates it 180 deg's this time //--------------------------- Creating the Heart object ----------------------------- void createHeart(){ // This method creates a large size heart JF[0]=0;KF[0]=0;OF[0]=0.1f; // symbol located at Form's center, using JF[1]=10;KF[1]=30;OF[1]=0.1f; // the "GraphicsPath". JF[2]=30;KF[2]=60;OF[2]=0.1f; JF[3]=60;KF[3]=70;OF[3]=0.1f; // To get the data, you sketch the heart on JF[4]=100;KF[4]=60;OF[4]=0.1f; // paper first and obtain the x,y coordinates JF[5]=130;KF[5]=30;OF[5]=0.1f; // of points on it's outline. JF[6]=150;KF[6]=0;OF[6]=0.1f; JF[7]=150;KF[7]=-30;OF[7]=0.1f; // Get as many points as you can for the curved JF[8]=135;KF[8]=-60;OF[8]=0.01f; // sections and only the start & end points for JF[9]=100;KF[9]=-100;OF[9]=0.01f; // "straight line" sections. JF[10]=0;KF[10]=-230;OF[10]=0.01f; JF[11]=-100;KF[11]=-100;OF[11]=0.01f; // JF[], KF[] are the x,y coordinates for the JF[12]=-135;KF[12]=-60;OF[12]=0.01f; // points. OF[] = tension. For a straight lines JF[13]=-150;KF[13]=-30;OF[13]=0.1f; // OF[]=0 At sections where you like the curve JF[14]=-150;KF[14]=0;OF[14]=0.1f; // not to bend too much or in other words to JF[15]=-130;KF[15]=30;OF[15]=0.1f; // be close to a straight line, assign small JF[16]=-100;KF[16]=60;OF[16]=0.1f; // value to the tension. JF[17]=-60;KF[17]=70;OF[17]=0.1f; JF[18]=-30;KF[18]=60;OF[18]=0.1f; JF[19]=-10;KF[19]=30;OF[19]=0.1f; JF[20]=0;KF[20]=0;OF[20]=0; // Make sure to make your start point also your // end point since it's a closed figure. oi=21;gm("cp"); // total rows=21, create path } } ========================================================================================= TUTORIAL: The comments supplied with the code actually explained it all. However, we need to clear a point here. All shape objects we are using (including text objects) are GraphicsPath objects. So what was new in this example? We needed to unify all shape objects in order to simplify working with them. The GraphicsPath is an object which you can add any shape object to. So, we have used this feature to unify them all. Whenever you call method gm() to create any shape, the method creates a new GraphicsPath, adds the shape you wanted to it and makes (gpp) a reference to that object. The new object represents your shape since it is the only item it contains. In this example, we needed to add some lines and curves to make a closed figure. So, we used the same GraphicsPath feature to do the job. So all shape objects, simple or complex are represented by the same object type. REMARK: Starting at PC# version 4.40, you have another way to generate (gpp) for the Heart sketch. You can scan the sketch and save it into file then supply the name of the file to method gm("bg") to create (gpp) for you. Example 11 of the "Imaging" chapter shows you how to do this job. Affine transform will be discussed in details at a later example. =========================================================================================

EXAMPLE 7: Here is an example on Special Effects - Depth. It shows how to display text in large size letters with 3-D look. ========================================================================================= 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() { cm("fwc");float wf=of; // Get Form's Client width and height, cm("fhc");float hf=of; // Store them for future use cls="b2";gm("sps"); // Prepare light blue paint lf=wf;of=hf;gm("crf"); // Fill form's background with it. fns="trp260"; // Set the font to TimesRoman, plain,260 xs="PC#"; // The string to be drawn with sp effects. float pos=-250; // Horiz position of each char to be drawn char[] C=xs.ToCharArray(); // Scan the string for (int i=0;i< xs.Length;i++) { // Read the string characters one by one os=""+C[i];gm("ct"); // Get the shape object for each char cls="s9s0";jf=pos;kf=0;id=20; // cls=brightest-darkest colors, location,depth ad=30;ks="d";gm("grs"); // ad=3D angle, ks="d" means select "depth" pos+=200; // Make each 2 chars 200 pixels apart } } } ========================================================================================= After method gm("grs") draws the 3D object, the present GraphicsPath object (gpp) which it ends with is for the front surface of the drawing. After you study the chapter of imaging, you'll know that this means that you can color the front surface of the drawing with any special color like "gold" or "chrome". Here is a new version of example 7 which draws a golden "PC#" string (It requires PC# version 4.40 or later): public class a : pcs { // Always remember, class name = file name public override void init() { j=825;k=425;dm("s"); // Resize Form base.init(); // Should be last statement in init() } public override void run() { cm("fwc");float wf=of; // Get Form's Client width and height, cm("fhc");float hf=of; // Store them for future use cls="b6";gm("sps"); // Prepare light blue paint lf=wf;of=hf;gm("crf"); // Fill form's background with it. fns="trp260"; // Set the font to TimesRoman, plain,260 xs="PC#"; // The string to be drawn with sp effects. float pos=-250; // Horiz position of each char to be drawn char[] C=xs.ToCharArray(); // Scan the string for (int n=0;n< xs.Length;n++) { // Read the string characters one by one os=""+C[n];gm("ct"); // Get the shape object for each char cls="o8Y6";jf=pos;kf=0;id=20; // cls=brightest-darkest colors, location,depth ad=30;ks="d";gm("grs"); // ad=3D angle, ks="d" means select "depth" gm("gc"); // Set the front surface of character as clip area lf=of=400;fls="images\\gold.bmp";gm("blf"); // Start a new bip using "gold.bmp" image scaled to be jf=pos;gm("br"); // slightly larger than (gpp) and draw it over (gpp) gm("gcn"); // Cancel previous setup of Clip area pos+=200; // Make each 2 chars 200 pixels apart } } } =========================================================================================

EXAMPLE 10: This example shows how to make the object you are drawing look elevated up or pushed 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) //-------------------- "Pushed 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, one 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 and a reflection at the top, we feel that the object is elevated up and when we see a shadow at the top and a reflection at the bottom, we feel that the object is pushed down. =========================================================================================

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="s7";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 background 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. =========================================================================================

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

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. The button itself will be transparent so the user will be clicking on the drawing. Make sure that the jewel file "x.jpg" is available. If not, run Example 11 to generate it. ========================================================================================= 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;cls="s79s70";ib=true;ims="x.jpg";cm("i"); // Create bt0 with background image cs="ch0";cus="Select a Shape";j=-250;i=190;o=40;cls="b0s3";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="b0s3";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 selected shape index to (s) cs="ch1";cm("gu"); // Get ch1 update c=cui; // Assign selected 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: Drawing the button: ------------------- We wanted both the foreground and the background colors of the button to be transparent. This is not completely allowed for controls. Foreground colors are always fully opaque even if we set them to be transparent. Background colors for most controls cannot be transparent either. Fortunately the button is one of few controls which can be of transparent background. The Label and Panel controls share this ability with the button. In method setup(), we made the assignments (ib=true;cls="s79s70") for the button. This means that we have requested the button to be "Flat" and to use for both foreground and background the color "s7" which is used for form's background and also for image's background. We selected the foreground to be fully opaque and the background to be fully transparent. Why did we want the button to be flat? This is because the standard botton has a three dimensional border which will prevent it from being invisible. The flat button also has a border except that its border is a rectangle drawn around it using the button's foreground color. So, we can make a flat button invisible by making its foreground color invisible. We can't make the foreground color transparent as mentioned before, but we can make it match the form's background color which will do the same job and this is what we have done. The background color can be made transparent by making its opacity digit "0". It also can be made invisible by selecting the color which matches the image's background color. We have done the two together which has actually been more than necessary. Making a drawing clickable: --------------------------- Using the same technique you can draw any object and make it clickable. This time we used an object which was saved into a file, but this is not necessary. You can draw the object on the present bitmap object (bip) and make (bip) the background image of a transparent button of equal size to its bounding rectangle. To set (bip) as the background image of any control assign "b" to (ims) and call cm("sg"). You can also do the same during setup using method cm("i") What could happen if an object is drawn on the top of a control? ---------------------------------------------------------------- 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") =========================================================================================

=============================================================================================== Scaling the image to be printed: ================================ Mode "prb" prints the present Bitmap object (bip) It allows us to set the position of the bitmap center relative to the center of the printable area of the paper in 1/100th of an inch unit. We do that by assigning the (x,y) components of (bip)'s position to (jf,kf) If we make no assignments to (jf,kf) the image will be centered into the page. Mode "prb" also allows us to set the width and height of the printed image by assigning them to (lf,of) They are also in 1/100th of an inch unit. Now, how can we calculate the necessary values of (lf,of)? Suppose that we like to match the width of the displayed image in inches with the width of the printed image (See the next Remark), how can we do it? Method gm("bR") can find for us (bip)'s resolution in Pixels/Inch over both the horizontal and vertical directions. So we can easily calculate the width in inches as follows: Width in inches = (Width in Pixels) / X-Resolution. Then all we need to do is to multiply this number by 100 and assign it to (lf) Similarly, we can calculate (of) Except that all this is unnecessary since it's the default. All you need to do if you like to match inch for inch is to supply (lf=of=0;) and method gm("prb") will do the calculations for you. If you like to assign values to (lf,of), we recommend assigning value to one of them only and assigning zero to the other one. This is because the method will replace the zero in this case with the value which makes the width to height ratio matches the width to height ratio of (bip) This should save you time and guarantee that the printed image will look like the original. REMARK: ------- The actual width of the image on your monitor may not match the calculated width in inches. This is because the width you see depends also on the monitor itself. The resolution amounts in pixels per inch which we use to calculate the image dimensions in inches come from the .NET class System.Drawing.Image. Printing large size images: --------------------------- Computer screens and print papers do not match in size. Standard paper size is 8.5" X 11" which means that paper's height exceeds its width. For computer screens, the opposite is true. Fortunately, we don't need to be concerned of the screen height since we don't draw on the Form directly, we draw on (bio) which can be of any height we choose and we can use vertical scrollbars. On the horizontal direction, we normally don't like to exceed the screen's width or install horizontal scrollbars although we can. The reason is that whatever exceeds the screen in width will normally not fit into standard size paper when printed. Whenever we have a large image to draw, the best to do is to create (bio) with same width as the form's and a height which makes the height/width ratio of the paper matches the height/width ratio of (bio) The outside dimensions of the "letter" size paper is 8.5 X 11 If you subtract 1 inch from all sides as margins, the net size would be 6.5 X 9. These are the numbers which you may like to use. In the next example, we are going to be using the "Printable Area" size which can be as large as 8.25 X 10.75. =============================================================================================== EXAMPLE 15: Create (bio) with full screen width and make it match printer's paper in height/width ratio. Draw something which can occupy (bio) in full then print it. =============================================================================================== public class a : pcs { // Always remember, class name = file name // Var's used: w,h = Width and height of printable area of page in 1/100th of an inch unit. // x,y = Calculated width and height of screen in pixels. // c = Used in color selection. public override void run() { //----------------------------- (a) Printing Text Lines ----------------------------- gm("dn"); // Stop display temporarely. gm("po"); // Open a new printing operation gm("pgw");om("ti");w=o; // Get paper PrintableArea's width, convert to (int) gm("pgh");om("ti");h=o; // Get paper PrintableArea'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. of=y;cm("fbv"); // Request vert scrollbar & (bio) height=y cls="s9";gm("ec"); // Paint (bio)'s background (necessary for scrollbar for (int k=-y/2;k< y/2;k+=100) { // Operation) Scan (bio) vertically and for (int j=-x/2;j< x/2;j+=100) { // horizontally and draw a colored circle each 100 c=(j+x/2)/100;if (c >7) c=0; // pixels. (c) is used to select one color for each cls="r0b0y0g0p0c0m0S9".Substring (c*2,2);gm("sps"); jf=j+25;kf=k;lf=of=25;gm("cef"); // circle. } } gm("dn"); // Resume display. lf=w;of=h;bip=bio;gm("prb"); // Assign (bio) to (bip) and print it so that it // covers entire printable area of page. gm("pc"); // Close printing operation. } } ==============================================================================================

DRAWING ON THE TEXT SCREEN ========================== The Text Screen is a very versatile display media. In addition to allowing both your program and the user to display text and images, file them and print them, it also allows the two to edit its contents. It can send any of its contents to the Clipboard and can also receive the Clipboard's content. This feature can easily be used to send your drawings to the Text Screen and insert them wherever you like there. Let us have an example. ========================================================================================= Example 16: Let us draw the same piece of jewelry which we have used in other examples on the text screen. In order to show that the Text Screen can contain combinations of text, pictures and dynamically generated drawings, we are going to display two text lines, one above the drawing and one below it. ========================================================================================= public class a:pcs { public override void init() { tia=toa="t"; // Use text screen for text input/output base.init(); // Initialize pcs } public override void run() { cls="r0";fns="trb18";os="Drawing on the Text Screen";tm();os="";tm(); // Display title cls="b0";fns="trb12";os="This text line comes before the drawing.";tm(); // Display first line on Text Screen ib=true;cm("fv"); // Make form invisible temporarely j=k=200;ib=true;cm("fs"); // Resize form to fit object cls="s7";gm("ec"); // Color background to match Text Screen. //--------------------- Drawing the object (No change in code) -------------------- 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 } //------------------------ Displaying (bio) on Text Screen ----------------------- imp=bio;sm("csi"); // Set (bio) into Clipboard cm("fsd"); // Return form to regular size. cm("fv"); // Return visibility to Form. os=" ";tm("d"); // Move cursor to wanted display position tm("ep"); // Text Screen edit-paste os="";tm(); // Move to next line cls="b0";os="And this one comes after the drawing.";tm(); } // Display second line on Text Screen. } ========================================================================================= TUTORIAL: While preparing the drawing, We wanted to reduce the form size to the size of the drawn object in order to eliminate the space around it. But since the form size also sets the Text Screen size, we had to resize the form back to original size after the drawing was complete. Also, we kept the Text Screen invisible during drawing for this same reason. The object was copied to the Clipboard while the form was small and pasted on the Text Screen after it has been returned to the original size. As you know each time the form is resized using cm("fs"), the Bitmap object (bio) with all the drawings on its surface are also resized by the same amounts horizontally and vertically. This means that if we have not changed visibility to the Text Screen we could have seen a larger elliptical piece of jewelry which would still be of no concern to us since we made our copy to the clipboard before the resizing took place. Displaying image files on the Text Screen is much easier, you assign to (ims) the image file name and call tm("dg") to display the image at the cursor.

=========================================================================================== CLIP AREA ========= (This section requires version 1.55 or higher) The GraphicsPath object (gpp) can be set as a clip area. A clip area is an area on the graphical output device which disallows drawing anything outside its borders. A negative clip area does the opposite. Drawings can appear only outside a negative clip area. To set (gpp) as a clip area call gm("gc") To set (gpp) as a negative clip area call gm("gc-") To add another (gpp) object to current clip area call gm("gc+") To modify current clip area by intersecting (gpp) with it, call gm("gc&") To modify it by xoring (gpp) with it call gm("gc^") and to reset the clip area call gm("gcn") ========================================================================================= Example 17: Create a large elliptical shape and make it a negative clip area, Create the graphical shape object of the text "PC#" and xor it with the clip area then paint the entire form with an image. See what you'll get. ========================================================================================= public class a : pcs { public override void init() { base.init(); } public override void run() { lf=700;of=300;gm("ce"); // Create an ellipse. gm("gc-"); // Make it a negative clip area. fns="trb260";os="PC#";kf=-20;gm("ct"); // Create (gpp) for the "PC#" text gm("gc^"); // Xor (gpp) with the clip area lf=60;of=30;fls="images\\icon.bmp";gm("blf"); gm("spt"); // Create a texture brush using icon.bmp image file lf=760;of=360;gm("cr"); // Create a form size rectangle gm("grf"); // Draw-fill the rectangle using texture brush } }