Liberty Basic is develeopped by Carl Gundel
Original Newsletter compiled by Alyce Watson and Brosco
Translation to HTML: Raymond Roumeas

The Liberty Basic Newsletter - Issue #65 - FEB 2000

© 2000, Cliff Bros and Alyce Watson

All Rights Reserved

In this issue:

Hard copy printing in Liberty BASIC with lbprnt01.dll

In future issues:


PRINTING WITH LBPRNT01.DLL

In Newsletter #63, we discussed several ways to achieve hard copy printouts using Liberty BASIC. We can use Liberty BASIC's own LPRINT function for text and the graphics PRINT function for graphicboxes and graphics windows. We can ask Notepad, or other default text editor to print text for us. We can use Dean Hodgson's excellent library, Deanslib.dll. We can also "do it all" with api function calls.

We discussed the vbprint.dll at length, and it is a great tool. If only it offered a few more functions...

I've had it in mind to write a printing dll for Liberty BASIC for some time, and all of this printing discussion has prompted me to give it a try. The result is not perfect, but it does offer some useful functions.


LBPRNT01.DLL FOR PRINTING IN LIBERTY BASIC

BY ALYCE WATSON

awatso-@wctc.net

© Alyce Watson, 2000

ALL RIGHTS RESERVED

 

LBprnt01.dll is being released as shareware. It is not crippled or time limited, and it contains no nags. The released version is the only version there is. Registration will be on the honor system. For use in commercial applications, the one-time registration fee is $15.00. For all other uses, the registration fee is determined by the individual user, with a suggested value of $1.00. This will help defray the cost of the many ink cartridges reams of printer paper that were consumed in writing and testing this. Note that anyone who has purchased the CDROM, Windows Programming for Everybody with Liberty BASIC need not register the DLL, except for commercial use. Send registration fee to:

Alyce Watson

3030 Buchberger Road

Wisconsin Rapids, WI 54494 USA


Thanks to these special people, who gave so unselfishly of their time, their energy, their patience, and their goodwill:

Without their help, this DLL would never have seen the light of day.

Thank you, friends.


FUNCTION LIST


GETTING STARTED

You must first open the DLL, of course!

Open "lbprnt01.dll" for dll as #lb

To begin a print job, you must call either PrinterInit or PrinterDialog. All other printing functions should be placed after one of these calls. When the job is ready to be sent to the printer, you must call EndPrint. You may initialize the printer, print, then call EndPrint as many times as you need within a program. When you are finished with all printing jobs, close the DLL:

close #lb

INITIALIZING THE PRINTER

You may use either of the following calls to initialize the printer. Use PrinterDialog if you want to give the user a chance to cancel the operation, to choose the printer to use, or to choose the number of copies to print. The window handle is the first parameter in the call. It is best to use your program window's handle for this parameter, but it may be set to zero. The return from the PrinterDialog function is the device context of the printer.

CallDll #lb, "PrinterDialog",_ 'must call this to start a document
h as short,_ 'handle of program window
pDC as short 'nozero if successful = printer DC

PrinterInit does not give the user a chance to cancel the operation, or to choose number of copies or printer. It also requires the window handle as the first parameter and it returns the printer device context. In this case, it will be the user's default printer.

CallDll #lb, "PrinterInit",_ 'init with no print dialog
h as short,_ 'window handle
pDC as short 'nonzero if successful = printer DC

 You cannot print anything if the initialization call fails, so be sure to trap that possiblity in your code. If pDC = 0, then you do not need to call EndPrint. Here is one way:

IF pDC = 0 THEN

notice "Print job cancelled!"

goto [loop]

END IF

 

When all items to be printed have been added to the document, then

call EndPrint to send the job to the printer. The EndPrint call will

release the DC of the printer and eject the final printed page.

After issuing this call, you will need to initialize the printer

again for a new print job.

 

CallDll #lb, "EndPrint",_ 'ends document, ejects final page

h as short,_ 'window handle

r as short 'nonzero if successful

 

If you have initialized with PrinterDialog, you can retrieve

the number of copies requested by the user with the GetNumberCopies

function. You cannot get other information, such as page selections

if the user chooses to print only part of the job, or print quality.

This function does not retrieve the number of pages in each job, but

the number of printouts requested by the user.

 

CallDll #lb, "GetNumberCopies",_ 'only works with PrinterDialog call

h as short,_ 'window handle

numbercopies as short 'number of copies chosen by user

 

IMPORTANT NOTICE

PrinterDialog and PrinterInit both return the device context of

the printer, and call StartDoc and StartPage. If you are familiar

with printer function calls to GDI.DLL, you may place your

own calls in amongst calls to the lbprnt01.dll. Calling

EndPrint calls EndPage and EndDoc and releases the printer DC.

 

---------------------------------------------------------

CREATE FONTS

 

All text will be printed using the font Courier New - 10pt, unless

you choose to create a font of your own. You do not need to create

a font, but you may do so. There are three ways to create a font

with this dll. The easiest way requires only the name of the font

face desired, and the fontheight in hundredths of an inch. A

fontheight of 25, for instance, would result in a font that is one

quarter of an inch high = 25/100 inch. Note that the height includes

the blank space between lines, which is called the "External Leading"

space. The actual font will be slightly smaller than the height you

specify. This simple font creation function is called EasyFont.

 

In Liberty BASIC, when we specify font names, we must replace any blanks

in the name with an underscore character. "Courier New" becomes

"Courier_New" in Liberty BASIC syntax. DON'T DO THAT HERE!! Please

leave blank spaces blank for these font creation functions. You must

terminate the string containing the font name with a null character,

which is chr$(0) Here is the correct syntax for specifying a font

name and height in this dll:

 

pfontname$="Courier New" + chr$(0) 'must be null terminated

height=24 'in hundredths of inch

 

The call to EasyFont requires the window handle, height parameter as

short, and the fontname parameter as a pointer. The function

returns the handle of the created font. If the return is 0, the

function was unable to create a font.

 

CallDll #lb, "EasyFont",_ 'easy create font

h as short,_ 'window handle

height as short,_ 'height in hundedths of inch

pfontname$ as ptr,_ 'null terminated, no LB underscores

hfont as short 'returns handle of font

 

 

You can create a font with additional attributes, with a call to

PrinterFont. It has a few more parameters; bold, italic, underline,

and strikeout. If any of these parameters is set to 1, that attribute

will be set. They can be used in any combination, so a font can be

both bold and underlined, for instance. If an attribute's parameter is

set to 0, that attribute will not be used in the font. The other

parameters are exactly the same as for the EasyFont call:

 

pfontname$="Courier New" + chr$(0) 'must be null terminated

'no underscores between words

height=30 'in hundredths of inch

bold=0 'do not make it bold

italic=1 'make it italic

underline=1 'make it underlined

strikeout=0 'do not make it strikeout

 

CallDll #lb, "PrinterFont",_ 'create a font with many attributes

h as short,_ 'window handle

height as short,_ 'height in hundredths of inch

bold as short,_ '0=normal 1=bold

italic as short,_ '0=normal 1=italic

underline as short,_ '0=normal 1=underline

strikeout as short,_ '0=normal 1=strikeout

pfontname$ as ptr,_ 'null terminated, no LB underscores

hfont as short 'returns handle of font

 

 

For the purists, there is another font creation function that allows you

to create fonts in point sizes, rather than in hundredths of an inch. There

are approximately 72 points in an inch. When you use a word processor such

as WordPad, the fonts are sized in points. All parameters are the same as

in the call to PrinterFont, except that the size attribute for the call,

PointSizeFont is in points instead of hundredths of an inch:

 

CallDll #lb, "PointSizeFont",_ 'create a font with many attributes

h as short,_ 'window handle

height as short,_ 'height in points - 72 pts per inch

bold as short,_ '0=normal 1=bold

italic as short,_ '0=normal 1=italic

underline as short,_ '0=normal 1=underline

strikeout as short,_ '0=normal 1=strikeout

pfontname$ as ptr,_ 'null terminated, no LB underscores

hfont as short 'returns handle of font

 

 

SET TEXT COLOR

 

You may choose an RGB color for text printing. It requires a struct

containing the color information. Color values are for red, green,

and blue, and each should be between 0 and 255. 0 means none of a

color, so rgb of 0,0,0 results in black. 255 is total saturation of

a color, so rgb of 255,255,255 is white. If you wanted pure red, you

would set that value to 255, and the others to 0. Here's an example:

 

struct col,_ 'holds info for text color

red as short,_ 'red value = 0-255

green as short,_ 'green value = 0-255

blue as short 'blue value = 0-255

 

col.red.struct = 255 '0-255

col.green.struct = 0 '0-255

col.blue.struct = 0 '0-255

 

CallDll #lb, "ChooseTextRGB",_

h as short,_ 'handle of window

col as struct,_ 'struct of color info

r as long 'nonzero if successful

 

If the user does not have a color printer, text will be printed

in black, no matter what color you set. This would be true

of a dot matrix printer, for instance.

---------------------------------------------------------

PRINTING TEXT

 

There are two functions that print text in this dll. Both

will print one line of text in the default font, or in the

most recently created font, and in the color from

ChooseTextRGB, if that function has been called. It is not

necessary to create a font or to set a text color. In that

case, defaults will be used.

 

 

**************************************************

********IMPORTANT NOTE ABOUT TEXT PRINTING********

**************************************************

 

There are two ways to print a line of text with this DLL.

Using PrintTextLocate allows the programmer complete control

over text location on the printed page. Starting new pages

is the responsibility of the programmer.

 

Using PrintTextLine lets the DLL print one line after another

at the proper line spacing. The DLL controls the location

of text on the printed page, starting new pages when needed.

 

Although these functions may both be used in the same print

job, it is best to use one or the other, and not both, to

preclude the possibility of one function overwriting text that

has been placed on the page by the other function.

 

**************************************************

********IMPORTANT NOTE ABOUT TEXT PRINTING********

**************************************************

 

 

PrintTextLocate

The first text print function allows the programmer complete

freedom over text location on the page. X location and Y

location are set in hundredths of an inch. Setting xloc to

200 would cause the start of the text to be two inches from

the left margin. Keep in mind that most printers allow a

printable width of about eight inches, and a printable height

of about ten and a half inches. Some newer printers will allow

nearly the full 8 1/2 inch width and 11 inch height.

 

You must use a null terminator on each line of text, as you

did for the fontname discussed earlier:

 

text$="Some words."+chr$(0)

 

You also need to determine the length of the text line to

print. Do NOT include the null terminator in this length,

so if you have added chr$(0) before determining the length,

remember to subtract 1.

 

length=len(text$)-1

xloc=100:yloc=200

CallDll #lb, "PrintTextLocate",_ 'print one line of text

h as short,_ 'window handle

text$ as ptr,_ 'text string to print

xloc as short,_ 'x location in hundredths of inch

yloc as short,_ 'y location in hundredths of inch

length as short,_ 'length of text string

r as short 'nonzero if successful

 

 

You can determine the maximum number of characters that will

fit across the width of the printer page, in the current

font, with a call to GetMaxCharsTotalWidth. This will tell

you how many characters will fit in a line of text if it

begins at the very left edge of the paper, and continues all

of the way to the right edge. You can use this value to

determine the maximum length of a line to print with

PrintTextLocate:

 

CallDll #lb, "GetMaxCharsTotalWidth",_ 'total characters from edge to edge

h as short,_ 'window handle

totalmax as short 'total number of chars that will

fit,

'if text starts at left edge

 

 

PrintTextLine

Using the previous function to print text requires the programmer

to keep track of the location of all text on the page. You

can eliminate this need by calling PrintTextLine. Calls to

this function will print a line of text in the current font and

color, and within the current margins. Each subsequent call will

advance the Y cursor the proper amount for the font size in use.

It doesn't matter if you change fonts for each line, the next line

will print at the proper distance from the previously printed line.

The parameters are similar to the PrintTextLocate call, but no

X and Y location are needed:

 

text$="Some words."+chr$(0)

length=len(text$)-1

CallDll #lb, "PrintTextLine",_ 'prints line, moves down automatically

each line

h as short,_ 'window handle

text$ as ptr,_ 'text string to print

length as short,_ 'length of text string

r as short 'nonzero if successful

 

If you need to advance the text printing location down the page more than

one line's height, then make a call to PrintBlankLine. This call can

be made as many times as needed to create the space desired.

 

CallDll #lb, "PrintBlankLine",_ 'move cursor down page the height of

one line

h as short,_ 'window handle

r as void 'no return

 

When calling PrintTextLine and PrintBlankLine, you do not need

to concern yourself with the location of the bottom of the page.

When the bottom of the page is reached, the page will automatically

be ejected, and a new page will begin. This takes the current margins

into account for all four sides of the page.

 

If you do need to know the location of the Y cursor, which is the Y

location to print the NEXT line with PrintTextLine, you may use

the function GetLineYPos, which returns the location of the Y cursor

in hundredths of an inch.

 

CallDll #lb, "GetLineYPos",_ 'cursor position for PrintTextLine

h as short,_ 'window handle

linepos as short 'position of y cursor in hundredths

 

Remember that the Y cursor is only used by PrintTextLine. In

PrintTextLocate, the programmer has complete control over the

location of the text on the page. If you are not careful, a call

to PrintTextLocate could overwrite lines printed with PrintTextLine.

Calling GetLineYPos will help you determine the lower extent of text

printed with PrintTextLine.

 

You may retrieve the current line height, as determined by the current

font, with GetTextLineHeight. This function retrieves the height of

a font, including the space between the previous line of text, and the

top of the font, which is called the External Leading space. This

line height value is used by the DLL in PrintTextLine to determine

the y position of each succeeding line of text. You may retrieve this

value for use in PrintTextLocate, for proper line spacing when you locate

text on the page. The line height is returned in hundredths of an inch.

 

CallDll #lb, "GetTextLineHeight",_ 'height for lines in current font

h as short,_ 'window handle

lineheight as short 'height in hundredths of text line

 

 

Notice that for both PrintTextLocate and PrintTextLine, only one

line of text at a time may be printed. For PrintTextLine, you

can make a call to GetMaxChars to determine the maximum number

of characters that can be printed across the width of the page,

considering the current page margins:

 

CallDll #lb, "GetMaxChars",_ 'max for PrintTextLine, current margins

h as short,_ 'window handle

maxchar as short 'total number of characters that will fit

'in a line within current page margins

 

You may eject a page and start a new page yourself whenever you

would like, by calling NewPage:

 

CallDll #lb, "NewPage",_ 'ejects page, starts new one

h as short,_ 'window handle

r as short 'nonzero if sucessful

 

You may retrieve the values for the maximum possible width

of a character in the current font, and the value for

the average width of a character, with the following two

functions. Maximum width and average width will be the same,

or very close to the same for a fixed width font. They might

vary greatly for a variable width font. In a fixed width font,

all characters occupy the same space, as on an old-fashioned

typewriter. In a variable width font, large characters, such as

an upper case letter "M" will take much more space than small

characters such as a lower case "i", a comma, a space, etc.

 

CallDll #lb, "GetMaxCharWidth",_ 'maximum width of char in current font

h as short,_ 'window handle

maxwidth as short 'max char width in printer dots

 

 

CallDll #lb, "GetAveCharWidth",_ 'average width of char in current font

h as short,_ 'window handle

avewidth as short 'ave char width in printer dots

 

---------------------------------------------------------

MARGINS for PrintTextLine

 

Margins are only significant when using the PrintTextLine

function. The default margins are one inch on all sides.

If you are using PrintTextLocate, you are not restricted,

and you may print right up to all edges of the paper. You

may change the margins that will be used by PrintTextLine

with the following four functions that allow you to change

only the margins desired. Remember, the default margins

are all one inch, and needn't be changed unless you desire

to do so. Margins are set in hundredths of an inch.

Choosing a margin of 50 would result in a half inch

margin: 50/100 = one half inch.

 

top=100 'top margin in hundredths of inch

CallDll #lb, "SetTopMargin",_

h as short,_ 'window handle

top as short,_ 'top margin in hundredths of inch

r as short 'nonzero if successful

 

right=80 'right margin in hundredths of inch

CallDll #lb, "SetRightMargin",_ 'OPTIONAL

h as short,_ 'window handle

right as short,_ 'right margin in hundredths of inch

r as short 'nonzero if successful

 

bottom=100 'bottom margin in hundredths of inch

CallDll #lb, "SetBottomMargin",_

h as short,_ 'window handle

bottom as short,_ 'bottom margin in hundredths of inch

r as short 'nonzero if successful

 

left=150 'left margin in hundredths of inch

CallDll #lb, "SetLeftMargin",_

h as short,_ 'window handle

left as short,_ 'left margin in hundredths of inch

r as short 'nonzero if successful

 

---------------------------------------------------------

PRINTER INFORMATION

 

There are four functions in the DLL that will tell you

information about the printer resolution. GetDotsInchWidth

will tell you how many printer dots are in one inch of

page width. My printer has 300 dots per inch. My previous

printer had 360 dots per inch width. My old dot matrix

printer has only 75 dots per inch width. You may also

find out the dots per inch height with a call to

GetDotsInchHeight. Why do we need both? Aren't they the

same? No! On some printers there are more dots in one

direction than in the other.

 

CallDll #lb, "GetDotsInchWidth",_

h as short,_ 'window handle

dpix as short 'dots per inch in width

 

CallDll #lb, "GetDotsInchHeight",_

h as short,_ 'window handle

dpiy as short 'dots per inch in height

 

The other measurements of printer resolution in the dll are

for total dots per width and height of the paper. In

general, the total dots per width will be equal to the

dots per inch width multiplied by 8 -- the number of inches

that may be printed by most printers. My printer has

300 dots per inch width, and 2400 total dots per page width.

In the same way, the total dots in the height will be equal

to the number of dots per inch in height multiplied by 10 1/2.

Here are the calls to get total dots:

 

CallDll #lb, "GetDotsTotalWidth",_

h as short,_ 'window handle

dotswide as short 'total dots in width

 

CallDll #lb, "GetDotsTotalHeight",_

h as short,_ 'window handle

dotshigh as short 'total dots in height

 

If you want to know the width of a page in printable inches,

then divide the Total Dots Width by the Dots per Inch Width.

 

inchesWide=dotswide/dpix

 

The same is true for height in inches:

 

inchesHigh=dotshigh/dpiy

 

---------------------------------------------------------

GRAPHICS

 

LINE

There are four graphics entities that can be printed with

the dll. The first is PrintLine. The parameters x1 and y1

specify the starting point of the line, in hundredths of an

inch, on the printed page. The parameters x2 and y2 specify

the ending points of the line. You may draw as many lines

as you would like.

 

CallDll #lb, "PrintLine",_

h as short,_ 'window handle

x1 as short,_ 'x origin in hundredths of inch

y1 as short,_ 'y origin in hundredths of inch

x2 as short,_ 'x end in hundredths of inch

y2 as short,_ 'y end in hundredths of inch

r as short 'nonzero if successful

 

 

RECTANGLE

Printing a rectangle is quite similar to printing a line. The

parameters x1 and y1 specify the coordinates for the starting

corner of the rectangle -- usually the upper left corner is used.

The parameters x2 and y2 specify the coordinates for the corner

opposite the starting corner. If the upper left corner was determined

by the x1, y1 parameters, then the x2, y2 parameters would specify

the coordinates for the lower right corner of the rectangle. All

coordinates are in hundredths of an inch locations on the printed

page.

 

CallDll #lb, "PrintRectangle",_ 'measure in hundredths of inch

h as short,_ 'window handle

x1 as short,_ 'x origin corner

y1 as short,_ 'y origin corner

x2 as short,_ 'x end opposite corner

y2 as short,_ 'y end oppposite corner

r as short 'nonzero if successful

 

 

ELLIPSE

The call to print an ellipse is very similar to the PrintRectangle call.

This is because the parameters also specify a rectangular shape, in

just the same way as they did in the PrintRectangle call. This

rectangle will not be visible, but it will be the bounding rectangle

for the ellipse. The ellipse will be drawn so that its edges intersect

the bounding rectangle on all four sides.

 

CallDll #lb, "PrintEllipse",_ 'measure in hundredths of inch

h as short,_ 'window handle

x1 as short,_ 'x origin corner - bounding rectangle

y1 as short,_ 'y origin corner - bounding rectangle

x2 as short,_ 'x end opposite corner - bounding rectangle

y2 as short,_ 'y end oppposite corner - bounding rectangle

r as short 'nonzero if successful

 

 

ROUND RECTANGLE

The call to PrintRoundRectangle is indentical to the PrintRectangle call

except that it contains two more parameters. The x3 parameter specifies

the width of a small ellipse that will be used to round the corners of

the rectangle. The y3 parameter specifies the height of the small

ellipse that will be used to round the corners. The larger these

numbers in relation to the size of the Round Rectangle, the more rounded

the corners will be. A small relative size of the x3 and y3 parameters

will create sharper curves on the corners of the round rectangle.

 

CallDll #lb, "PrintRoundRectangle",_ 'measure in hundredths of inch

h as short,_ 'window handle

x1 as short,_ 'x origin corner

y1 as short,_ 'y origin corner

x2 as short,_ 'x end opposite corner

y2 as short,_ 'y end oppposite corner

x3 as short,_ 'corner ellipse width

y3 as short,_ 'corner ellipse height

r as short 'nonzero if successful

 

---------------------------------------------------------

COLOR IN GRAPHICS

 

PRINTER PEN

Objects are drawn with black lines unless changed by programmer. The

drawing pen can be altered in width, style and color, by calling the

PrinterPen function. You may set the color for any pen style. As

in the ChooseTextRGB function, the values for red, green, and blue may

be between 0-255, with 0, 0, 0 being black. You may set the size of

the pen for the pen style _PS_SOLID. This size will be in logical

units, which in this case are printer dots. You may call the function

GetDotsInchWidth to determine the best number of dots for the pen size,

if this is important in your graphics. For instance, with a dots per

inch of 300, a size of 75 would give a one quarter inch thick pen.

 

You may set the style of the pen also. All styles other than a solid

pen default to size 1. Here are the possible styles:

 

'0 = _PS_SOLID PS = PEN STYLE

'1 = _PS_DASH

'2 = _PS_DOT;

'3 = _PS_DASHDOT

'4 = _PS_DASHDOTDOT

'> 4 THEN default is _PS_SOLID

 

'NOTE if style > 0 then size reverts to 1 pixel

 

The PrinterPen function returns the handle of the created pen,

if successful.

 

CallDll #lb, "PrinterPen",_ 'shapes outlined with pen

h as short,_ 'window handle

size as short,_ 'size in dots

style as short,_ 'pen style

pred as short,_ 'red value 0-255

pgreen as short,_ 'green 0-255

pblue as short,_ 'blue 0-255

hPen as short 'returns handle of pen

 

 

PRINTER BRUSH

Objects are filled with hollow brush unless changed by programmer.

Unless you specify a brush, your drawn objects will just be

outlines. You must again specify the rgb color values for the

brush, just as for the PrinterPen and ChooseTextRGB functions.

You must also choose a brush style. To fill shapes with a solid

color, choose a style value of 6. The other style patterns are

as follows:

 

'0 = _HS_HORIZONTAL HS = HATCH STYLE

'1 = _HS_VERTICAL

'2 = _HS_FDIAGONAL

'3 = _HS_BDIAGONAL

'4 = _HS_CROSS

'5 = _HS_DIAGCROSS

'6 will give a solid fill = no pattern

 

The PrinterBrush function returns the handle of the created brush,

if successful.

 

CallDll #lb, "PrinterBrush",_ 'fills graphics entities

h as short,_ 'window handle

style as short,_ '6=solid, 0-5 are hatch styles

pred as short,_ 'red value 0-255

pgreen as short,_ 'green 0-255

pblue as short,_ 'blue 0-255

hBrush as short 'returns handle of brush

 

If you have created a PrinterBrush, then have a need to

return to a hollow brush to draw outline figures only,

then call PrinterNullBrush.

 

The PrinterNullBrush function returns the handle of the created

brush, if successful.

 

CallDll #lb, "PrinterNullBrush",_ 'allows you to return to default

hollow figure

h as short,_ 'window handle

hBrush as short 'returns handle of brush

---------------------------------------------------------

SCREEN PRINT

 

*************** WARNING ************************

IN TESTS, THIS FUNCTION SOMETIMES RESULTED IN

A GRAYSCALE PRINTOUT, RATHER THAN A COLOR PRINTOUT.

WHEN IT PRINTS IN COLOR, IT MAY NOT APPEAR THE

SAME AS THE SCREEN DISPLAY VERSION.

*************** WARNING ************************

 

As we've discussed in a previous newsletter, the graphics

printing capabilities of Liberty BASIC have some limitations.

The PrintWindowArea function will allow some graphics printing

flexibility. The first parameter required is the window's

handle. YOU MUST USE THE HANDLE OF THE GRAPHICS WINDOW OR

GRAPHICBOX - you may not use 0 for this parameter in this

function. After the window handle parameter, there are four

parameters that specify the location and size of the screen

image to capture. You need not take the entire image. The xorg

and yorg are the coordinates of the upper left corner of the

desired area, in PIXELS! Remember that pixels are the logical

units of the display, so the measurements for the screen are in

pixels. The width and height parameters tell the function how much

of the screen to copy to the printer, in pixels. If you wanted to

capture the image from x = 10, y = 33, and take an area that is

100 pixels by 227 pixels:

 

xorg=10

yorg=33

width=100

height= 227

 

The next four parameters are the ones that tell the printer where

to locate the screen image on the page, and how large to make it.

These values are all given in hundredths of an inch. The params,

pxorg and pyorg will define the location of the upper left corner

of the screen image on the printed page, in hundredths of an inch.

If you wanted the image to begin 2 1/2 inches from the left side

of the page, you would have pxorg = 250.

 

The next two parameters tell the printer how wide and high you

want to make the image -- again in hundredths of an inch. If

you wanted the image to be four inches wide, then pwidth = 400.

 

CallDll #lb, "PrintWindowArea",_

h as short,_ 'valid window handle NOT = 0 !

xorg as short,_ 'starting x pixel for print

yorg as short,_ 'starting y pixel for print

width as short,_ 'pixel width from screen

height as short,_ 'pixel height from screen

pxorg as short,_ 'x loc on page in hundredths of inch

pyorg as short,_ 'y loc on page in hundredths of inch

pwidth as short,_ 'width of image on page in hundredths of inch

pheight as short,_ 'height of image on page in hundredths of inch

r as short 'nonzero if successful

 

There have been some reports that this function results in a

grayscale printout on some systems. Please take this into

consideration when using this function.

---------------------------------------------------------

BITMAP PRINT

 

You may print a hard copy of any bitmap that is loaded

into memory. The bitmap may be loaded with Liberty BASIC's

LOADBMP function, or it may be an image loaded from a third-

party DLL. You must have the handle of the bitmap to pass

into the call. If the image was loaded with an add-on DLL,

you will likely get the handle of the bitmap as the return from

the loading function. In Liberty BASIC, we get the handle

of a bitmap with the HBMP function. The syntax would be:

 

loadbmp "party","party.bmp"

hbitmap = hbmp("party")

 

After the window handle and the bitmap handle, you must specify

the coordinates for the location and size to print the bitmap

on the paper. These values are in hundredths of an inch.

The point x1, y1 will determine the upper left corner for

bitmap placement on the page, in hundredths of an inch. If

you wanted to print the bitmap 3 1/4 inches from the top, then

y1 = 325.

 

You must also set a width and height to print the bitmap, in

hundredths of an inch. If you want the bitmap to be 4 inches

wide, then pwidth = 400. The function returns nonzero if

successful.

 

CallDll #lb, "PrintBitmap",_

h as short,_ 'window handle

hbitmap as short,_ 'bitmap handle

x1 as short,_ 'org x on page in hundredths

y1 as short,_ 'org y on page in hundredths

pwidth as short,_ 'hundredths of inch wide to print

pheight as short,_ 'hundredths of inch high to print

r as short 'nonzero if successful

 

 

To aid in sizing and proportion when printing a bitmap, there

are functions that return the bitmap's dimensions. You may

use these for scaling/sizing purposes. To retrieve the

width of a loaded bitmap, pass the handle of the bitmap into

the function BitmapWidth, and the function returns the width

of the bitmap in pixels. The BitmapHeight function will

return the height of the bitmap in pixels. You can use these

values to set the width and height of the printed copy of the

bitmap. If you multiply the bitmap width and bitmap height

by the same factor, then the proportions will remain the

same. It is not necessary to keep the proportions the same,

so you may use different scaling factors if you wish.

 

CallDll #lb, "BitmapWidth",_

h as short,_ 'window handle

hbitmap as short,_ 'bitmap handle

bmpwidth as short 'bitmap width

 

CallDll #lb, "BitmapHeight",_

h as short,_ 'window handle

hbitmap as short,_ 'bitmap handle

bmpheight as short 'bitmap height

 

If you wanted the bitmap to be twice as large (in hundredths

of an inch) on the printed page as its width on the screen,

then you would set the width and height like so:

 

pwidth = 2 * bmpwidth

pheight = 2 * bmpheight

 

If you wanted the bitmap to be out of proportion, you might

have something like this:

pwidth = 3 * bmpwidth

pheight = int(2.3 * bmpheight)

 

Note that you should use the INT function if there is a chance

of a fractional value, because Liberty BASIC will crash

if you try to use a fraction as a parameter in an api call.

---------------------------------------------------------

DEMOS

 

There are several demonstration programs included with this

newsletter that use many of the functions in the dll.

There are demos using the following line-wrap routine.

 

There is also a great demo by Bill Jennings, with a better

line-wrap routine, so thanks AGAIN, Bill!

 

It would be very, very nice if people would post code that

uses this DLL, so that others can benefit, and so that the

author of the DLL knows if this tool has been useful.

 

---------------------------------------------------------

LINE WRAP

 

This DLL will print one line of text. It will not automatically

wrap lines that are too long to fit on the width of the page.

 

Please consider whether the VBprint.dll we discussed in an

earlier newsletter would be better for your needs, if your

program needs to print large blocks of text easily.

 

The function GetMaxCharsTotalWidth will tell you the approximate

number of characters that will fit on a line, if the line is

to begin at the left printable edge of the page, and continue

to the right printable edge. You can use this value to

determine the length to make lines to insure that they will not

be truncated when using PrintTextLocate. This formula uses the

average character width to calculate the maximum number of

characters, so it will only be approximate.

 

The function GetMaxChars will tell you the approximate number

of characters that will fit on a line using PrintTextLine

with the current margins. You can use this value to determine

the length to make lines, so that they will not be truncated.

This formula also uses the average character width to calculate

the maximum number of characters, so it will only be

approximate.

 

If you would like to send a large block of text to the printer,

without concerning yourself with line-wrapping, the following

subroutine is provided for your convenience. You will need

to place the text string into a variable called TextBlock$

and then call GOSUB [print.text.block]. Be sure to paste

the routine below, unchanged, into your code. The beginning

and end of the routine are clearly marked. The block of

text can be obtained from an opened file, like this:

 

open "readme.txt" for input as #rm

TextBlock$ = input$(#rm, lof(#rm))

close #rm

gosub [print.text.block]

 

The contents of a text editor may be retrieved and printed

using this subroutine, like this:

 

print #1.texted, "!contents?";

input #1.texted, TextBlock$

gosub [print.text.block]

 

You may also hard-code the text into your program like this:

 

TextBlock$="Here is some text to print. It can be as long as you like."

gosub [print.text.block]

 

SUBROUTINE FOR PRINTING WITH LINE-WRAP FOLLOWS:

---------------------------------------------------------

'-----------------------------------------------

'-----------------------------------------------

' BEGIN LINE-WRAP ROUTINE

' DO NOT CHANGE THE CODE BELOW!

'

' LBPRNT01.DLL MUST BE OPENED

' AS #lb

'

' PRINTER MUST BE INITIALIZED WITH

' PrinterDialog

' OR

' PrinterInit

'

' SEND IN A BLOCK OF TEXT IN

' A STRING CALLED TextBlock$

' CALL GOSUB [print.text.block]

'-----------------------------------------------

'-----------------------------------------------

 

[print.text.block]

gosub [get.max.chars.in.line] 'returns max.char

gosub [print.wrap] 'wraps and places in temp file tf.tmp

 

Open "tf.tmp" for input as #5

While eof(#5)=0

Line input #5, temp.line$ 'send one line of text to printer

 

[fix.tab.stops]'removes chr$(9) and replaces with blank spaces

if instr(temp.line$,chr$(9))>0 then

blank=instr(temp.line$,chr$(9))

blank=instr(temp.line$,chr$(9))

 

temp.line$=left$(temp.line$,blank-1)+space$(4)+Mid$(temp.line$,blank+1)

if instr(temp.line$,chr$(9))>0 then goto [fix.tab.stops]

end if

 

line.length=len(temp.line$)

temp.line$=temp.line$+chr$(0)

 

gosub [print.text.line.from.block]

wend

close #5

kill "tf.tmp"

return

 

 

[print.text.line.from.block]

CallDll #lb, "PrintTextLine",_

h as short,_ 'window handle

temp.line$ as ptr,_ 'text string to print

line.length as short,_ 'length of text string

r as short 'nonzero if successful

RETURN

 

 

 

[get.max.chars.in.line]

CallDll #lb, "GetMaxChars",_

h as short,_ 'window handle

max.char as short 'returns maximum chars in line

RETURN

 

 

[print.wrap] 'word wrap for printing based on max.char formula

newL$=""

CrLf$=chr$(13)

ist = 1

while ist < len(TextBlock$)

nst = instr(TextBlock$, CrLf$, ist)

if nst = 0 then

line$ = mid$(TextBlock$, ist)

ist = len(TextBlock$)

else

line$ = mid$(TextBlock$, ist, nst-ist)

ist = nst + 2

if line$ = "" then newL$ = newL$ + CrLf$

end if

while line$ <> ""

if len(line$) <= max.char then

newL$ = newL$ + line$ + CrLf$

line$ = ""

else

if instr(line$, " ") < 1 then

newL$ = newL$ + left$(line$, max.char) + CrLf$

line$ = mid$(line$, max.char+1)

else

char$ = ""

index = max.char + 1

while char$ <> " "

char$ = mid$(line$, index, 1)

index = index - 1

wend

newL$ = newL$ + left$(line$, index+1) + CrLf$

line$ = mid$(line$, index+2)

end if

end if

wend

wend

open "tf.tmp" for output as #5

print #5, newL$

close #5

cursor normal

return

 

'-----------------------------------------------

'-----------------------------------------------

' END LINE-WRAP ROUTINE

' DO NOT CHANGE THE CODE ABOVE!

'-----------------------------------------------

'-----------------------------------------------


Brosco and Alyce have written a Book for Liberty BASIC,

which is available in electronic form on a CDROM.

For details: http://alyce.50megs.com/sss/cd.htm


Newsletter compiled and edited by: Brosco and Alyce. Comments, requests or corrections: Hit 'REPLY' now! mailto:brosc-@orac.net.au or mailto:awatso-@wctc.net