* ------------- copy and paste this code ---------------------------
* first you must load the printer.prg
* ------------- copy and paste this code ---------------------------
|
Drawing Lines
The first object we will look at is the line. The syntax for the line is very simple:
p.Line1(nTop, nLeft, nBottom, nRight, nPenTag)
Whoops, what is a pentag? A pen tag is much the same as the font tag used in the defineFont() method. A pen tag is simply a variable used to reference a pen. What is a pen? A pen is an object used to draw lines in windows. A pen defines line width, color and style (solid, dashed, etc.) To define the pen that you want to use to draw lines, you simply use the definePen() method:
p.DefinePen(Tag, nStyle, nColor, nWidth)
Tag is either
a number or a character string you want to use to keep track of a particular
pen. nStyle is
one of the several styles identified in the printer.h file. So you must remember to #include
"printer.h" in any programs in which
you are going to use pens. Here is a list from the include file:
* Pen Styles *
#define PS_SOLID 0 #define PS_DASH 1 #define PS_DOT 2 #define PS_DASHDOT 3 #define PS_DASHDOTDOT 4 #define PS_NULL 5 #define PS_INSIDEFRAME 6 |
Here is the definition of the various pen styles:
The nColor parameter is an RGB number. The RGB macro is included in the printer.h include file. To create an RGB number, you can use the dBASE function getcolor() and plug the 3 values returned into the RGB macro:
PEN STYLES Value Meaning PS_SOLID Creates a solid pen. PS_DASH Creates a dashed pen. (Valid only when the pen width is 1.) PS_DOT Creates a dotted pen. (Valid only when the pen width is 1.) PS_DASHDOT Creates a pen with alternating dashes and dots. (Valid only when the pen width is 1.) PS_DASHDOTDOT Creates a pen with alternating dashes and double dots. (Valid only when the pen width is 1.) PS_NULL Creates a null pen. PS_INSIDEFRAME Creates a pen that draws a line inside the frame of closed shapes produced by graphics device interface (GDI) output functions that specify a bounding rectangle (for example, the Ellipse, Rectangle, RoundRect, Pie, and Chord functions). When this style is used with GDI output functions that do not specify a bounding rectangle (for example, the LineTo function), the drawing area of the pen is not limited by a frame.
RGBNumber = RGB(nRed, nGreen, nBlue)
The last parameter, the nWidth, is simply the width of the line in thousandths of an inch (millimeters if you are using the SetMapMode("MM")).
Now we are ready to print some lines on our report. Remember to cut and paste the basic code into your .prg. Then insert the following code into the spot I told you at the start of this article (the code spot). Here is an example of creating a pen and drawing a line:
p.definePen('red', PS_SOLID, RGB(255,
0, 0), .2)
p.Line1(2, .3, 2, 7.5, 'red')
These two lines of code, plugged into the “code spot” should produce a red line 2 inches from the top of the page, 3 tenths of an inch from the left side, 7.5 inches wide. Try it and see. Don't forget the #include "printer.h".
One small note on pens: if you are going to use any style other that PS_SOLID, PS_NULL or PS_INSIDEFRAME, set the width to zero. Any other style pens are always 1 pixel wide.
Drawing Boxes
The next object we want to take a look at is the box or rectangle. It would be simple to draw a box with the line() method by just drawing 4 connecting lines. But since windows provides a API call to draw rectangles, it is easier just to use it. The syntax for drawing a rectange is almost identical to drawing a line:
p.rectangle(nTop, nLeft, nBottom, nRight, penTag, brushTag)
Here we introduce a new parameter, the brushTag. The brushTag is the variable to hold the reference to an new item, the brush. Any object that is enclosed, such as a rectangle, can have its interior painted using the brush object. Again, there is a new method for creating the brush:
p.DefineBrush(Tag, nStyle, nColor, nHatch)
The tag and nColor parameters are the same as for the line method. The nStyle and nHatch parameters are from the definitions in the printer.h include file:
* Brush Styles #define BS_SOLID 0 #define BS_NULL 1 #define BS_HOLLOW BS_NULL #define BS_HATCHED 2 #define BS_PATTERN 3 #define BS_INDEXED 4 #define BS_DIBPATTERN 5 * Hatch Styles
|
Here is the definition of the above from the Windows SDK (software development kit):
If the Style is the BS_PATTERN style, nHatch must be a handle to the bitmap that defines the pattern. If the Style is the BS_SOLID or the BS_HOLLOW style, nHatch is ignored.
STYLES Value Meaning BS_DIBPATTERN Specifies a pattern brush defined by a device-independent bitmap (DIB) specification. BS_HATCHED Specifies a hatched brush. BS_HOLLOW Specifies a hollow brush. BS_PATTERN Specifies a pattern brush defined by a memory bitmap. BS_NULL Equivalent to BS_HOLLOW. BS_SOLID Specifies a solid brush.
HATCHES Value Meaning HS_BDIAGONAL 45-degree upward hatch (left to right) HS_CROSS Horizontal and vertical cross-hatch HS_DIAGCROSS 45-degree cross-hatch HS_FDIAGONAL 45-degree downward hatch (left to right) HS_HORIZONTAL Horizontal hatch HS_VERTICAL Vertical hatch
NOTE: Any type of brush using bitmaps IS NOT SUPPORTED by the printer class at this time. (But maybe it will be in the not too distant future)
To print a example of an unfilled box, let's plug this code into our “code spot”:
p.rectangle(2, 2, 4, 4, 'DEFAULT', 'DEFAULT')
This will produce a 2 inch square box located down 2 inches from the top of the page and 2 inches from the left margin. The box will have no fill and the line used to draw the box will be .01 inches wide. Now the first question that should come to mind is: What are the “DEFAULT” pen and brush. There are “DEFAULT” pens, fonts and brushes defined by the printer class upon instantiation of the object. I simply used the default pen and brush, which will suffice many times.
In this next example we will define our own pen
and brush:
p.definePen('blue', PS_SOLID, RGB(0, 0, 255), .05) p.defineBrush('bluehatch', BS_HATCHED, RGB(0, 0, 255), HS_CROSS) p.rectangle(2, 2, 4, 4, 'blue', 'bluehatch') |
Now let's plug this into our “code spot” and run it. It produces a box in the same location as the first example, except with a blue line and filled with blue hatching.
A variation on the rectangle is the round cornered rectangle. This is produced using the roundRect() method in the printer class. Here is the syntax for the roundRect:
p.RoundRect(nTop, nLeft, nBottom, nRight,
;
nEllipseWidth, nEllipseHeight,
PenTag, BrushTag)
As you can see, we have added two parameters, nEllipseHeight and nEllipseWidth.
These parameters describe the height and width of the rounded corners of
the roundrect.
You should just do a little experimenting to get the feel of it.
Plug this example into our “code spot” and try it on for size:
p.definePen('blue', PS_SOLID, RGB(0, 0, 255), .05) p.defineBrush('bluehatch', BS_HATCHED, RGB(0, 0, 255), HS_CROSS) p.RoundRect(2, 2, 4, 4, .25, .25, 'blue', 'bluehatch') |
This example prints a rectangle just like the one above except it has quarter inch radius rounded corners.
Printing Images
Finally, let's print one or two of the various type graphics images that the printer class can handle. It can print JPG, JIF, GIF, BMP, DIB, RLE, TGA and PCX format images.
p.AtSayImage(nRow, nCol, xBitMap, nWidth, nHeight, nTopStart, nLeftStart)
Only nRow, nCol and xBitMap parameters are required. If you are going to use the nTopStart and nLeftStart, you must specify nWidth and nHeight. You will understand when you see the explanation of nTopStart and nLeftStart below.
This method prints the image contained in various file formats (see above) at the location specified by nRow, nCol (upper left hand corner of the image) and size it to nWidth and nHeight. If nWidth and nHeight are not specified, it will attempt to print at the default size of the image. The xBitMap parameter can be either the filename of the image, i.e. “picture.jpg” or the bitmap handle obtained by using the NViewLib.dll (32-bit) or NViewL16.dll (16-bit) from NView Library, which is free and downloadable from:
http://home.att.net/~knishita/software/nviewlib.zip
Here is the code for obtaining the hBitMap handle:
#ifdef __vdb__ extern chandle NViewLibLoad(cstring, clogical) NViewLib.dll #else extern chandle NViewLibLoad(cstring, clogical) NViewL16.dll #endif hBitMap = NViewLibLoad(cImageFile, .f.) |
One reason for not including the loading of the bitmap handle within this method is that you may want to print the same image on multiple pages, such as printing letterheads. If that were the case and the method loaded the bitmap each time, it would considerably increase the print time. You can better control this in your program code. With this method (function) the AtSayBitMap() method becomes no longer needed. The nTopStart and nLeftStart parameters are used when you want to print a form that you have scanned in and its size is the same as a sheet of paper (8.5" x 11"). Most printers won't let you print to the very edge of the paper, so these parameters let you start printing at the left and upper limits of the ability of the printer. This results in the image being printed in exactly the same place as the original form that was scanned. What is the benefit of this? You can take a ruler and measure where on the original form you want to print text and it should be the same on the printed form. If you don't use these parameters, the form will be shifted down and to the right of the original.
Here's and example of printing an image:
p.AtSayImage(2, 2, "dBASE75.jpg",
3, 2)
Plug that code into our “code spot” and try it. It will print the dBASE logo at the very upper printable edge of the paper, the size of the image will be 3 inches wide by 2 inches high. That bitmap is included with this article just in case you don't have it on your drive.
As you can see, it is pretty simple to print lines,
boxes and images at the exact location you desire onto your report using
the methods provided in the printer/preview class.