September Nineteenth 2005 From: Bob Zale, President PowerBASIC, Inc. Subject: Printing and Windows-Only Printers =========================================== Dear Bob, Welcome to the latest edition of the PowerBASIC Gazette! In the coming months, we'll continue a series of articles which explore the many new functions in PowerBASIC 8 for Windows, as well as the PowerBASIC Console Compiler 4. Today we'll concentrate on printing, and in particular, how to make best use of Windows-Only printers. We've got some great sample programs, too. You can download both the source and the executables, so you can test them, and see how easy it is, even if you don't have one of the new compilers yet! We've got charting samples, to create pie charts and 3-D bar charts. With a file you can $INCLUDE in your programs today. We even have a code sample for one method of PRINT PREVIEW! But first, look at what the new compilers offer... Printing Background =================== PowerBASIC offers an excellent PRINT engine for any type of printer. It's fast. It's complete. And it handles all those messy Windows details for you... automatically! PowerBASIC supports two general classes of printers. We categorize them as Line Printers or Host Printers. Generally speaking, we recommend using Host Printers whenever possible, as they have far greater capabilities, including an extensive graphics package. A line printer is one which will accept standard ASCII text and the associated control codes, such as CR, LF, and FF. A line printer is identified by the port to which it is attached (LPT1, etc.) because data is sent directly to the port, not through a device driver. You print to Line Printers by using the LPRINT family of functions, just as you've probably done for years with operating systems like DOS. A host printer is one which works through the Windows printing system with a Windows printer driver. These printers are sometimes known as "Windows-only printers", "GDI printers", or "USB printers". They can achieve device independence because the printer driver handles the task of converting ASCII text into the manufacturers binary format used by the printer. Generally speaking, host printers expect to receive a map of the printed output, pixel-by-pixel, which is supplied by the device driver. They have no intrinsic ability to translate text into pixels. You print to Host Printers by using the XPRINT family of functions. Some printers have dual capability, and can be used as either a line printer or a host printer. In this case, you can use either LPRINT or XPRINT functions, depending upon which group is more appropriate to your needs. LPRINT Features =============== LPRINT is used primarily for simple text output, and uses a small number of functions. In contrast to single-tasking systems like DOS, you'll first need to select a printer. For example: LPRINT ATTACH "LPT1" This will attempt to select the printer attached to the port "LPT1". If successful, the LPRINT$ function returns the name of the attached printer. If not, it returns a zero-length string. Selection of a printer in this manner assures that two applications won't try to use the same printer at the same time. Once a line printer has been successfully attached, use LPRINT to output text characters to the printer. Once all the data has been sent, it is recommended that the printer be detached, permitting other applications to access it. Detach a printer device by executing LPRINT CLOSE. You can use LPRINT to output both string and numeric expressions to the printer. Any number of expressions may appear on a single line: LPRINT x$, y&; TAB(42); z$ By default, a carriage return and linefeed is inserted at the end of each printed line. A semi-colon between expressions is an optional nul delimiter which leaves the printer column position unchanged. A comma moves the printer position to the next column of 14 positions each. A trailing semi-colon suppresses the final CR/LF. XPRINT Capabilities =================== XPRINT is the real workhorse of the PowerBASIC print engine. This is the extended print function which works with Windows-Only printers. In its simplest form, it can be used in a way that's very similar to LPRINT. Just attach a host printer, XPRINT some text, then detach the printer so others can use it. It can be just that simple. But what if you want more? We've got you covered! You can print plain text or fancy text. Any font. Any size. Any color. Bold, italic, underline, or strikeout. You can mix fonts, any combination of fonts, on a single page. Plus, you can position the text at any location on the page, measuring point by point. Then, you get bitmaps. Create them from scratch, load them from a resource, load and save a BMP file on disk. You can copy them, stretch or shrink them. Print them anywhere on a page. Even mix their colors with those colors which already exist. Of course, you also get a complete range of graphic primitives. Lines, points, fills. Circles, ellipses, rounded rectangles. Boxes and pie sections. Ovals, polygons, polylines, and more. You control the line width, the color, and the line style. You control just about everything. Finally, you get scaled coordinates. You can design the coordinate system that suits your particular need, even if you want fractional floating point values. For example, you might specify the upper left corner as (0, 0), and the lower right corner as (1, 1). That means the center of the window is simply (0.5, 0.5). Of course, you can use any values in the range of a single-precision floating point variable. If x2 is greater than x1, coordinates grow larger as they move to the right. Otherwise, they grow larger as they move to the left. If y2 is greater than y1, coordinates grow larger as they move downward. Otherwise, they grow larger as they move upward. It's all under your control. It should be noted that GRAPHIC functions and XPRINT functions were built to be almost parallel. There's a GRAPHIC LINE and an XPRINT LINE. A GRAPHIC ARC and an XPRINT ARC. And so on. Once you've created text and graphics for the screen, you can virtually duplicate it for XPRINT! Or vice versa for a real "Print Preview"! XPRINT ATTACH ============= Since Windows is a multi-tasking operating system, you must first select and attach a printer. This assures that two applications won't try to use the same printer at the same time. XPRINT ATTACH offers 3 options: XPRINT ATTACH {CHOOSE | DEFAULT | printername$} If CHOOSE is specified, PowerBASIC opens a Choose Printer common dialog so the user can select a printer from the list of installed printers. If DEFAULT is specified, the default printer is used. Or, if a string expression is given, it's presumed to evaluate to the name of a specific printer. If the printer is attached successfully, the XPRINT$ function returns the name of the printer. If not, it returns a zero-length string. Another interesting feature of this version is the new PRINTER$ function. Called repeatedly, it will let you retrieve both the printer name and the port name for every printer connected to the computer. This may be particularly valuable if you wish to create your own unique version of a "choose printer" dialog. Once a host printer has been successfully attached, you'll XPRINT your report. XPRINT your graphics. XPRINT your charts, Of course, when you're done, don't forget to detach the printer with XPRINT CLOSE. This frees up the printer for another application to use. Perhaps even more important, host printers normally won't even begin to print to the paper until the print job is closed. XPRINT Position =============== Some XPRINT functions use the concept of an implied "page position" to determine the default point on the page where the next operation will take place. In PowerBASIC, we use the keyword POS to refer to this position (See XPRINT GET POS and XPRINT SET POS to alter or retrieve this position). POS is also commonly known as the LPR (Last Point Referenced) or even NPR (Next Point Referenced). For most purposes, you can consider these three terms to be synonymous. When a new page is created, the default POS is set to (0,0), which is the upper left corner. Unless you specify otherwise, the first XPRINT operation starts at that point, and the completion point is then saved as the new POS. So, if you draw a line from (0,0) to (100,100), that last point (100,100) is saved as the new POS. The next line you draw would then, by default, start at (100,100), and then automatically save its completion point as the updated POS for next time. The "XPRINT Position" (POS) is used by XPRINT, XPRINT LINE, and XPRINT GET/SET PIXEL. Other XPRINT functions neither use nor update POS. XPRINT Color ============ PowerBASIC allows you to specify any color as an RGB value. That's a long integer value in the range of 0 to &H00FFFFFF. It is used to specify a very precise color to various PowerBASIC functions and Windows API functions. The lowest three bytes of the value each specify the intensity of a primary color which combine to form the resultant color. Byte 1 (the lowest) represents the red component, byte 2 the green, and byte 3 the blue. They can each take on a value in the range of 0 to 255. Byte 4 (highest) is always 0. The RGB() function can be used to easily create an RGB value from the three component values. PowerBASIC has predefined a number of equates for common colors (%black, %blue, %cyan, %green, %gray, %ltgray, %magenta, %red, %white, %yellow). You may use these whenever it is convenient to do so. You can set the default foreground and background colors with XPRINT COLOR: XPRINT COLOR foreground& [, background&] Both the required foreground color and the optional background color are specified as RGB values. If either parameter is -1, the default foreground or background color is used. If the background parameter is -2, the background is made transparent. Many Xprint statements allow you to override the default color, and use an explicit color for that statement only. This has no effect on the default colors, which can only be changed by execution of another XPRINT COLOR statement. Bounding Rectangle ================== Some XPRINT functions, namely those involved with the drawing of curves (XPRINT ARC, XPRINT ELLIPSE, and XPRINT PIE), utilize the concept of a "bounding rectangle" to determine their size and position on the printer page. A bounding rectangle is defined as the smallest rectangle which can be drawn around the circle or ellipse. For example, let's say you wish to draw a circle centered at position (500,500), which has a radius of 400 pixels. The upper left corner (x1,y1) of the bounding rectangle would be at (100,100), while the lower right corner of the bounding rectangle would be at (900,900). Execute this program to demonstrate... Function PBMain() Xprint Attach Default Xprint Box (100,100)-(900,900), 0, %red Xprint Ellipse (100,100)-(900,900), %blue, %gray, 6 Xprint Color %magenta, -1 Xprint Set Pos (100,100) Xprint "(100,100)" Xprint Set Pos (500,500) Xprint "(500,500)" Xprint Set Pos (900,900) Xprint "(900,900)" Xprint Close End Function XPRINT TEXT =========== Printing of text, in various forms, is likely the most used function of a printer engine. When a host printer is first attached, PowerBASIC specifies a default font of COURIER NEW. The point size of this default font is determined by the printer driver. You can change to any other font, style, and size with the XPRINT FONT statement: XPRINT FONT fontname$, points&, style& fontname$ is the name of the font. points& is the size of the font, specified in points. style& is the style attribute, a combination of: 0=normal 1=bold 2=italic 4=underline 8=strikeout For example, a style& value of 3 specifies a combination of both bold and italic attributes. Windows offers both fixed fonts (like Courier New or Lucida Console), and proportional fonts (most of the rest). In a fixed font, every character is precisely the same size. In a proportional font, all characters are the same height, but the width varies from one to the next. For example, the character "W" is much wider than the character "i". This gives a pleasant appearance to the text, but poses a challenge to the programmer. If your text has a lot of wide characters, you may just print right off the right side of the page. What if you want to center text on the page, or even right-justify it? PowerBASIC offers XPRINT TEXT SIZE, for just that purpose! XPRINT TEXT SIZE expr$ TO x!, y! You can measure the size of a string to be printed with Graphic Text Size, before you ever display it. Be sure the font, point size, and text style have already been set, then execute it. expr$ is the string expression you wish to measure. x! and y! are variables which receive the text width and height. The sizes returned are specified in pixels, dialog units, or world coordinates, depending your choice at creation and your use of the GRAPHIC SCALE statement. Once you have the print size, it's a simple calculation to determine the appropriate start position. The XPRINT statement is used to send text to the printer page. It is displayed in the font, size, and style currently selected by the XPRINT FONT statement, as described above. XPRINT [expr] [;expr] [;] An expr is a numeric or string expression. XPRINT can output any number of expressions to the printer page. A semicolon can be used as a separator between multiple expressions on the same line. XPRINT x$; y&; z$; Drawing begins at the last point referenced (POS) by another graphic statement, or the point specified by GRAPHIC SET POS. The upper left corner of the text is positioned at the POS. Upon completion, the POS is moved to the left margin of the next line. However, if a trailing semi- colon is included, movement to the next line is suppressed. Generally speaking, you should avoid the embedding of control codes like CR, LF, and FF (characters 13,10,12) in a string expression, as they may not produce the expected results. Instead, use XPRINT without a parameter to move to the next line, or XPRINT FORMFEED to start a new page. So, is it possible to emulate the printing style of LPRINT with the XPRINT statement? Of course... it's very straightforward: Function PBMain() XPRINT ATTACH Default XPRINT "Line 1" XPRINT "Line 2" XPRINT "Line 3" XPRINT CLOSE End Function This simple code prints three lines of text on the default printer. It's just that easy! Now you can enhance it... change the color, font style, add some borders and other graphics... The possibilities are endless. Printer Pages ============= As you've likely noticed, printing with XPRINT is oriented to full pages of text and graphics. You can contruct parts of a page in any sequence that's convenient for you. As each page is completed, you just execute an XPRINT FORMFEED to start a new one. But just how do you determine the size of a page, and other printer-specific details? XPRINT GET CLIENT TO x, y This retrieves the client size (printable area) of the current printer page, assigning the values to x and y. XPRINT GET LINES to x, y This retrieves the number of text lines which can fit on one page, given the current font size. XPRINT GET MARGIN TO x1,y1,x2,y2 This retrieves the margin size (non-printable area) of the printer page, assigning the values to the listed variables. XPRINT GET ORIENTATION TO orent& This retrieves the orientation (portrait or landscape) of the printer page, assigning the value to the listed variable. A complementary function to set the orientation is also provided. XPRINT GET PPI TO x, y This retrieves the resolution (points per inch) of the printer page, assigning the values to the listed variables. XPRINT GET QUALITY TO qual& This retrieves the print quality setting for the current printer page. A complementary function to set the quality level is also provided. XPRINT GET SIZE TO x, y This retrieves the total paper size of the current printer page. XPRINT Graphic Functions ======================== So, what else can be done with XPRINT? Here's a partial list... XPRINT ARC draws an arc or a portion of an ellipse. XPRINT BOX draws a square/rectangle with square or rounded corners. XPRINT CANCEL aborts the current print job. XPRINT CHR SIZE retrieves the size of a single character. XPRINT CLOSE detaches the current host printer. XPRINT COPY copies a bitmap to the host printer page. XPRINT ELLIPSE draws a circle or ellipse on the host printer page. XPRINT FORMFEED starts a new host printer page. XPRINT GET DC retrieves the device context handle for the printer. XPRINT GET MIX retrieves the current color mix mode. XPRINT GET PIXEL retrieves the color of a specific pixel. XPRINT LINE draws a line on the host printer page. XPRINT PIE draws a pie section on the host printer page. XPRINT POLYGON draws a polygon on the host printer page. XPRINT POLYLINE draws a polyline on the host printer page. XPRINT RENDER prints a bitmap loaded from a resource or disk file. XPRINT SCALE defines a custom coordinate system for the printer page. XPRINT SET MIX specifies a new color mix mode. XPRINT SET PIXEL sets a new color for a specified pixel. XPRINT STRETCH copies and resizes a bitmap to the host printer page. XPRINT STYLE specifies a drawing style for various XPRINT statements. XPRINT TEXT SIZE calculates the total print size of a string. XPRINT WIDTH sets the line width for various XPRINT statements. XPRINT$ returns the name of the attached host printer Put it all together? ==================== Hopefully, we've shed some light on printer functionality in PowerBASIC. In just a few paragraphs, we've covered all the basics of Extended Printing with XPRINT. I hope you agree it's been very straightforward. So now, let's put it together into a little XPRINT program... FUNCTION PBMain () XPRINT ATTACH Default XPRINT GET CLIENT TO x&,y& for i& = 1 to 20 x1& = RND(0&,x&) x2& = RND(0&,x&) y1& = RND(0&,y&) y2& = RND(0&,y&) clr& = RND(0,&HFFFFFF) crnr&= RND(0,40) wid& = RND(1,25) XPRINT WIDTH wid& XPRINT BOX (x1&,y1&)-(x2&,y2&),crnr&,clr& next XPRINT CLOSE End Function A simple program to XPRINT 20 random boxes! Random colors and sizes. Random line width and corner style. Just to give you a hint of what might be done with other XPRINT statements! You could add other code to draw arcs, circles, lines, ellipses, pie sections, polygons, polylines, and more! You can draw objects pixel by pixel. Use bitmaps, even create them from scratch. You can set color mix modes, even copy bitmaps, or stretch them to fit! We'll get into the other functions in the upcoming Gazettes. Stay tuned. {smile} Is it really that easy? ======================= Absolutely. Just jump right in and try it. You'll be amazed at what you might do with some practice. When you find some good code, please post it on the PowerBASIC Forums: http://www.powerbasic.com/support/pbforumsWe'd love to see some of your latest code! So would others, and they'll respond in kind! Let's fill up the Source Code forum today... Lots more to follow on the web site... and the next Gazette! Ready for some sample programs? =============================== They're hot! PowerBASIC CHART -- a charting library you can #INCLUDE in your code. An example of PRINT PREVIEW. More. Download source and executables at: http://www.powerbasic.com/files/pub/demos/pbchart.zip http://www.powerbasic.com/files/pub/demos/textview.zip It's all in there! Time for a "Hard Break" {smile} =============================== Please indulge me for one moment? If you haven't yet upgraded to the new compilers, now is certainly the time! Check out all the great new features on any of the following pages... PB/CC 4.0: http://www.powerbasic.com/products/pbcc/ PB/WINDOWS 8.0: http://www.powerbasic.com/products/pbdll32/ PowerBASIC FORMS: http://www.powerbasic.com/products/pbforms/ PowerSHIRT 1.0: http://www.powerbasic.com/products/pbshirt/ PB/WIN 8 is attractively priced at $199, while PB/CC 4 is just $169. Upgrades from versions 7 and 3 are just $99 and $89 respectively. PowerBASIC Forms is priced at $99, while the upgrade to version 1.5 is $39. You can order by replying to this email. You can call us today at (888) 659-8000 or (941) 473-7300, place an e/order on our secure web site (www.powerbasic.com), or even mail it in. But no matter what method you choose, please do it today and do it with confidence. Every product PowerBASIC ships for physical delivery is offered with a money-back guarantee for a full 30 days from the transaction date. The next Gazettes will cover more graphics, printing, and other topics. Like signed and unsigned BIT FIELD variables. THREADED variables for Thread Local Storage. ARRAY ASSIGN. Many new CONSOLE functions. FIELD for dynamic structures. New error processing functions. Even KEY functions, DESKTOP, and much, much more. Be sure you have the latest compilers... You won't want to miss this! Regards, Bob Zale, President PowerBASIC Inc. p.s. Don't forget PowerSHIRT version 1.0! The new PowerBASIC T-Shirt! It's a high quality, black T-Shirt, emblazoned with "PowerBASIC.COM", and a personal motto "I Compile Without Compromise". You couldn't be more stylish! The new PowerSHIRT 1.0 is available in sizes M/L/XL/XXL/XXXL, and priced at just $19.95. http://www.powerbasic.com/products/pbshirt/