application will use these functions, it is probably best to render them
invisible so your users will not be distracted or confused. Use
modi comm preview.wfm at
the command line to edit the file, and just comment out the code for these
buttons in Preview.wfm as
shown below. The commented-out code is in BOLD.
CLASS myTBar(lMapi) of ToolBar
this.imagewidth = 24
this.flat = true
this.floating = false
* if lMapi = .t.
** Open Preview File Button
** Save Preview File Button
// First Page Button
The p.nLine property, its cohorts, and other related positional properties
Thep.nLineproperty contains a value (defaulting to inches) that is used by the Printer class to specify the vertical position in the various AtSay()functions. In conjunction with the NextRow()andSetFont()functions, it is your connection to a very nice behind-the-scenes system which keeps track of where, vertically, on the page the current data is being written. Although you can always just use a decimal value (in inches) instead ofp.nLineto specify the vertical position of anything you print on the page, p.nLine is the best way to go for printing multiple lines of text. This is because the NextRow()function increments p.nLineby an amount that is appropriate for the current font height. That font height is stored in p.nLineInc(line increment) when you set the font via p.SetFont().
Whenp.StartPage()is called, p.nLineis automatically set to the height of the current font (assuming a font has been set) plus the offset to the start of the printable part of the page (see p.nTopOffseta few paragraphs below). This is done so that the vertical position does not default to zero (physical edge of the paper) where the printer cannot print.
11pt Arial has a height of 0.169", and a top offset for a laser printer
might be 0.11". So, p.StartPage()setsp.nLineto
0.169 + 0.11 = 0.279". Test this by inserting the following lines just
but be sure you have called p.SetFont()prior
to starting the page:
msgbox("p.nTopOffSet is " + ltrim(str(p.nTopOffSet,5,3)))
msgbox("p.nLineInc is " + ltrim(str(p.nLineInc,5,3)))
msgbox("p.nLine is " + ltrim(str(p.nLine,5,3)))
Then, each time p.NextRow() is called, it increments p.nLine by 0.169" or a multiple of it as specified in the NextRow() parameter. For example, p.NextRow(5) increments p.nLine by 0.169*5 = 0.845".
The p.EndPage() method also resets p.nLine to the font height (p.LineInc) plus p.nTopOffSet.
Important note about p.nLine: Although p.nLine is automatically incremented by p.NextRow(), you also have access to it programatically. For example, if you are printing labels in two or three columns on the page and wish to shift to the top of the next column of labels, just re-assign p.nLine to the appropriate value for the top label and printing will move there on the next AtSay(). And, with the next p.NextRow(), the value for p.nLine will be incremented.
Vic has also
provided us with info from the printer driver — the offsets from the physical
edges of the page to the beginning of the printable areas: p.nTopOffset
the distance from the physical top of the page to the beginning of the
printable area. Moreover p.nLeftOffset
the analogous value for the left edge of the page. If you want to start
printing as high on the page as possible, and to print as far to the left
as possible, you could use these properties. For example,
p.AtSay(p.TopOffset + p.nLineInc, p.LeftOffset, "As high and as far left as printably possible...")
Of course, as long as a font has been previously set, p.StartPage already sets p.nLine to p.TopOffset + p.nLineInc so you don’t actually have to do this yourself.
related property is p.nPageWidth.
This value represents the physical width of the page minus the widths of
the unprintable areas on both sides of the page. So, for an HP4000 LaserJet
printing in portrait orientation, the value of p.nPageWidth
7.953". This makes sense, since laser printers can’t print closer to either
edge than about 0.25"; so accounting for both sides of 8.5"-wide paper,
the printable page width should be about 8". To specify the far right edge
of the printable area as you would to maximally right-justify, use
p.AtSayRight(p.nLine, p.nPageWidth + p.nLeftOffset,"This is as far to the right as can be printed.")
The above specifies that the horizontal position be, from the physical left edge of the page, 7.953 + 0.263 = 8.216" to the right. That should be right about at the limit of printability on the right side. Since the right-alignment AtSayRight() is used, the text will be printed to the left of that point.
Fix “Invalid subscripterence” bug in Printdlg.wfm that chokes on incomplete printer entries in config.sys
of the Printer class may have this one fixed, but if not, this bug will
surface only on Win installations that have a missing port parameter for
one or more of the printers in the list of installed printers in config.sys.
Use modi comm printdlg.wfm at
the command line to edit the file. Search for “Procedure Setup” (about
line #604), then scroll down to the section of code shown below and add
the lines shown in BOLD:
nLen = aDevices.size
aPrinters = new array(nLen, 3)
form.aPrinters = new array(nLen)
for i = 1 to nLen
cDevice = aDevices[i]
cBuffer = space(1000)
nResults = WinAPIGetProfileString('Devices', cDevice, "", cBuffer, 1000)
aTmp = this.tokenize(substr(cBuffer, 1, nResults), ',')
aPrinters[i, 1] = cDevice
aPrinters[i, 2] = aTmp
aPrinters[i, 3] = aTmp
catch (exception e)
form.aPrinters[i] = " "
form.aPrinters[i] = cDevice
Enable strikeout font
include strikeout “appearance” for fonts in Printer.prg, but he has provided
code to enable it if you need it. You’ll need to use
modi comm printer.prg at
the command line to make changes in the two sections of code shown below.
Use Ctrl-f to find the locations in the code. The new code that
you’ll add is shown in BOLD:
* create a logfont structure to hold font
sLogFont = LogFontStruct()
sLogFont.setMem('lfStrikeOut', iif( this.lStrikeOut, 1, 0))
sLogFont.setMem('lfFaceName', padr(alltrim(cName), 32, chr(0)))
* font properties
this.aFonts = new assocarray() && array to hold the fonts
this.cFontTag = 0 && current font tag
this.hFont = 0 && used to hold handle to the font in use
this.nFontBold = 700 && set higher to increase bold weight
this.hOldFont = 0 && save hDC's original font for ResetDC()
this.lStrikeOut = .f. && set to true for strikeout fonts
appearance (1 or more of bold, underline, italics, strikeout) of a font
is part of the structure of the font (unlike color, which doesn’t affect
the shape of the characters), the strikeout appearance must be specified
when the font is defined. This is analogous to defining a bold, italics,
or underline font, but cannot (yet) be accomplished via a parameter in
Here is an example of defining a 10-point, not bold, not underline, not
italics “Courier New” font with strikeout appearance, and whose tag is
p.lStrikeOut = .t.
p.DefineFont(4, "Courier New", -10, .f., .f., .f.)
p.lStrikeOut = .f.
Then use p.SetFont(4) to turn on the font (assuming Printer object is called “p”).
Visual dBASE 7.x users
Open your Project, then drag/drop from the appropriate windows in Navigator all the files listed above. The one exception, if your application won’t use the AtSayImage() function, is NVIEWLIB.DLL. It’s easy to tell if there are any files missing from the Project — just Build your application, load the exe and try to run a preview or report — you will get an error if you left any of the files out.
For InstallShield Express, you will also need to include any DLL files that you use from the Printer class. Load InstallShield and open the file for your application, then look for “Specify Components and Files”:
Click the Groups and Files line. Under Groups, click the “+” for “Program Files”.
This is where you specify all of the non-BDE files to be deployed with your application — your exe file, tables, image files, help files, etc. Load Explorer (you can use their Launch Explorer button), and drag into the File Groups window the DLL files you’ll need: Preview32.dll, and, if you’ll be using AtSayImage(), Nviewlib.dll.
If you accidentally drag a file in that you don’t need, remove it from the list by highlighting it and pressing the Del key.
Then click OK to accept the additions, and save this new configuration.
Visual dBASE 5.x users
When you compile, include in the Files to Compile all the files listed above. The one exception, if your application won’t use the AtSayImage() function, is NVIEW16.DLL. It’s easy to tell if there are any files missing from the Project — just compile your application, load the exe, and try to run a preview or report — you will get an error if you left any of the files out.