home *** CD-ROM | disk | FTP | other *** search
- DOCUMENTATION FOR TURBO PASCAL PRINTER UNITS
-
- These units are for use in Turbo Pascal Windows Programs. They are shareware. You may use
- these units in any non-commercial products freely. You may copy the programs and the documentation
- and distribute them freely. If these units are to be incorporated into a commercial product, or if you wish
- source on disk, please send $25.00 to OptiCom, Inc, Box 16-1127, Miami, FL 33116. Our phone
- number is (305) 271-5138, and our CompuServe ID is 71250,71. If you register the product, I will send
- you irregular updates of these objects as I improve them.
-
- These objects, all source code and the contents of this document are copyright (c) 1991 OptiCom,
- Inc. We would sincerely welcome any comments/criticism/ideas you might have about these objects.
-
- The idea for these objects and the information in this document came from several sources. The
- objects themselves are loosely based on the printer classes contained in the Actor Development
- Environment, an excellent product of the Whitewater Group. Other material came from Charles Petzold's
- Programming Windows, the Microsoft SDK, the Turbo Windows Manuals, Compuserve and several
- friends and associates.
-
- Files on this disk:
- pDevice.pas Formal printer object, tPrnDevice.
- printer.pas Printer Object, tPrinter.
- repPrn.pas example of a report printer derived from the printer class.
- testPrn1.pas example file printer program, using the tPrinter object.
- testPrn2.pas example file printer program, using the reportPrinter object.
- test.res resource file
- prt.res resurce file
- printer.doc This document
-
-
- GENERAL OVERVIEW
- These objects are designed to provide an interface between a printer and an application running
- under Windows. The structure of these objects is such that you should not have to modify them to add
- functionality or change their behavior. You should create descendants of the objects to add additional
- features. An example of this is the ReportPrinter object, in the file RepPrn.pas. The reportPrinter object
- adds several features to the printer unit to handle headings and page size. Having learned the basics of
- OOP in the Actor environment, I have come to appreciate the advantages of adhering as strictly as
- possible to the principles of OOP. The Actor environment is pure OOP. That means that everything
- (and I mean everything!) is an object. The main advantage of OOP programming is the ease of
- modifying and extending the objects that you create. I hope these objects will prove to be good examples
- of this type of programming.
-
- These objects have been written with the OOP philosophy in mind. There is no access to the
- instance variables of an object outside that object's scope. All access to instance variables is through the
- methods of the object. Modifications to be made to the objects are made through descendants, not by
- modifying the code of the object. This is illustrated by the ReportPrinter object.
-
- This document is divided into several sections. The first discusses the relationship between
- Windows and the printer. It covers, in a general manner, the calls to Windows contained in the objects.
- I have tried to provide enough information to make clear what I am doing in each object, and so that the
- objects can be extended to suit your own needs. The other sections discuss the objects themselves and
- the sample programs. Each object section contains an explanation of the declared types in the unit, the
- object's instance variables and methods, and a bit about what the object is supposed to do. The sections
- on the sample programs discuss the nature of the programs, and how they use the objects to print.
-
- PRINTING IN WINDOWS
- It used to be that all you had to do to print something was USE the printer, and let fly. With
- some well placed WriteLn statements and judicious spacing, you could produce reasonable output. Not
- any more. Under Windows, printing requires almost as much programming as some small applications!
-
- To a Windows application, sending output to a printer is not much different than sending output
- to a window. The application actually sends its output to Windows, and Windows handles the mechanism
- of getting it where it is supposed to go. In general, printing under Windows requires the following steps:
- 1. The application must retrieve information about the current printer from the WIN.INI file.
- 2. The application must create a device context (a handle) for the printer.
- 3. Output is sent to the device context.
- 4. The application communicates with the printer device driver using escape codes.
- 5. Windows activates the print spooler to manage the print job.
-
- In addition to these basic steps, an application can also display a dialog box to allow a user to
- cancel a print job that is being spooled. This requires the instantiation of an Abort procedure to notify
- windows about the status of the print job.
-
- Windows' management of each print job revolves around the concept of a document. You can
- think of each, complete print job as a document. This applies no matter how large the output will be.
- Each time a new print job is started, that print job is one document. Since it is possible that more that
- one document may be printing at the same time, each individual print job must be kept separate from any
- other print job to avoid mixing them up during output. The application must notify Windows when a
- document is going to start. When printing has finished, the application must notify Windows that the
- document has ended. This notification is done using escape calls.
-
- In the following section, some of the concepts introduced above will be discussed in greater
- detail.
-
- ABORT PROCEDURE: An abort procedure is known as a callback function. It is a function in an
- application that is called by Windows during a print job. The function returns a boolean value indicating
- whether the user has canceled the print job. During normal processing, messages sent to the abort
- function are translated and dispatched back to Windows. As long as the print job is not canceled, the
- function returns a TRUE value to Windows. If the print job is canceled, the function returns FALSE,
- letting Windows know the job was canceled.
-
- In order to implement an abort procedure, it is necessary to provide a dialog box and an abort
- function. The dialog box generally contains a brief message ('Sending job to spooler...') and a cancel
- button. Pressing the cancel button should set a variable accessible to the abort function to FALSE. The
- abort procedure must be declared as a EXPORTed function, and must return a boolean value. This is
- done in the AbortProc method of the printer object. The abort function may not be a method of an
- object, since object methods may not be exported. This also means that the print dialog may not be
- contained in an instance variable of an object, since the Abort procedure would not have access to it.
- Finally, the variable set by the Cancel method of the print dialog must be global to the unit in which these
- two items are declared. Again, the process necessary for creating an abort mechanism may be seen in
- the Printer.pas file.
-
- The next step is to notify Windows of the existence of the abort function. This is done by
- sending the SETABORTPROC escape code to Windows, with a far pointer to the abort function as a
- parameter. This pointer is obtained through the MakeProcInstance method. MakeProcInstance creates
- a far pointer that is bound to the data segment of the instance of the application that contains the abort
- function. This is so that when Windows calls the abort function, it uses data in the current instance. The
- application instance refers to the instance handle of the current application. A handle is a number that
- uniquely identifies a program running under Windows. Since multiple instances of a program share code,
- it is necessary for Windows to keep track of who is doing what. The call to MakeProcInstance returns
- a tFarPointer which is then used in the SetAbortProc escape call. The SetAbortProc escape call passes
- the pointer to the abort function to Windows.
-
- If an application does not set an abort procedure, it is quite likely that any errors will cause the
- program to crash. One common error is a lack of disk space for spooling. In the abort procedure, the
- application can decide whether to wait for some disk space to be freed, or to cancel the print job. If an
- print job terminates abnormally, or if it is canceled, the GDI automatically cancels the print job. In this
- case, the application should not attempt to end the print job using escape calls.
-
- Both the abort procedure and the print dialog box must be instantiated prior to issuing the
- STARTDOC escape call to create the document.
-
- DEVICE CONTEXT: When an application wants to use a device, it must obtain a handle for that device
- from Windows. This handle is known as the device context. Through the device context, an application
- has access to various devices attached to the computer. The device context is actually a data structure
- maintained by the GDI, containing information about the particular device to which it belongs. For
- example, when output is sent to the printer, the GDI uses the information contained in this data structure
- to properly format the output. A device context works very much like a file in a Pascal program. Once
- you have assigned a file name to a file variable, all access to the file passes through the file variable.
- In a Windows program, all access to the device must 'pass through' the device context handle.
-
- Device Mode: The device mode function is part of the printer device driver. These drivers are supplied
- by the manufacturer and distributed with Windows. When you call DeviceMode, you are calling a
- routine in a DLL. The deviceMode call is responsible for displaying the printer dialog box, allowing a
- user to change the printer parameters. The name of the function in a driver written for Windows 3 is
- ExtDeviceMode. In drivers for earlier versions of Windows, the function is DeviceMode. There are
- several differences between these two functions. The most important one is that in the DeviceMode call,
- any changes to the device parameters are reflected in the WIN.INI file. These changes will affect all
- current and future sessions of Windows. In the ExtDeviceMode procedure, the programmer has the
- option to make the changes permanent, or to maintain them for the current session only.
-
- ESCAPE CALLS: Escape calls allow an application to communicate with a printer device driver. The
- escape sequences contain commands and information for the driver. They can also be used to obtain
- device-specific information. There are quite a number of escape codes that can be used (57, I believe).
- These are listed in the Turbo Windows Reference guide under Printer Escape Codes.
-
- GDI (Graphics Device Interface): The GDI is a programming language that acts as an interface between
- an application, the printer device driver and the print manager. An application does not have to know
- anything about the devices with which it will communicate. As long as the application uses the GDI to
- access the devices, all of the output functions will be handled by Windows. This is known as device-
- independence. As you will see, close communication is necessary between an application, Windows and
- the printer driver to print a document.
-
- WIN.INI file: The WIN.INI file plays an important part in the printing process. In the method
- GetPrinterParms, this file is queried to obtain information about the current printer. Information in the
- WIN.INI file is stored under application name and key name headings. Printer information is contained
- under the application name '[windows]' and the key name 'device'. The key name is followed by the
- currently selected printer, the name of it's device driver, and the port to which the printer is connected.
- For example, a typical device keyword might look like this:
-
- Device=IBM Proprinters,PROPRINT,LPT1:
-
- This tells us that the currently selected printer is an IBM Proprinter, the driver is
- PROPRINT.DRV, and the printer is connected to LPT1. The settings in this file can be modified by the
- DeviceMode call to the printer device driver. It is also possible, using the ClearEnv method, to force
- a device to read the WIN.INI file to obtain the current printer parameters.
-
-
- ===============================================
- PRINTER OBJECT REFERENCE
-
- tPrnDevice, Contained in file pDevice.Pas
-
- INSTANCE VARIABLES
-
- hPrintDC Holds the printer device context. This variable is instantiated by the DCcreated method.
-
- hWindow Contains the handle to the parent window from which the printer object was created.
- This variable is instantiated by the Init method, using a value passed from the application.
-
- docName The name of the document that is being printed. This variable is instantiated in the
- BeginDoc method. The document name is used with the STARTDOC escape call to
- uniquely identify the document being printed. This allows the print manager to manage
- separate print jobs, without their interfering with one another. When the print manager
- is active, this name appears on the status line for the selected printer.
-
- Device The name of the printer. This is obtained through a call to getPrinterParms, which
- retrieves the information from the WIN.INI file
-
- Driver The name of the device driver associated with the device. This information is also
- obtained through the getPrinterParms call
-
- dMode a tDevMode data structure. Although it is not used extensively in these objects, this
- structure holds a great deal of information about the printer and device driver. It is used
- by DeviceCapabilities and by the getExtDeviceMode to hold information about a printer
- device driver.
-
- noSpooler A boolean variable that is set in the GetPrinterParms method, based on the value for
- spooler in the WIN.INI file. It indicates whether the spooler is active or not.
-
- prnPort The port to which the object will print. This information is obtained from the WIN.INI
- file through a call to getPrinterParms.
-
-
- TYPES
-
- devArray An 80 character string used in the unit to hold various values.
-
- prnErrors Enumerated type defining the different errors that can occur during the printing process.
- These are used as parameters when calling the PrnError method.
-
- pPrnDevice A pointer to the tPrnDevice Object.
-
- tPrnDevice The formal printer object. You should not create an instance of this class. Instantiate
- tPrinter instead.
-
- tGetDevMode This is a template for a windows function call to display the device driver dialog box for
- drivers not written for windows 3.0.
-
- tGetExtDevMode This is a template for a windows function call to display the device driver dialog
- box for device drivers written for windows 3.0.
-
-
-
- METHODS
-
- AbortPrn Aborts the current print job.
-
- BeginDoc Sends the STARTDOC escape call to windows to indicate the start of a document. This
- is an important call. Included in the Escape call is the name of the document to be
- printed. This name is used by the GDI to identify a unique print job, and prevents
- documents longer than one page from being mixed in with other documents. The job
- name appears in the print manager list of jobs. The STARTDOC call should always be
- paired with an ENDDOC or ABORTDOC escape call.
-
- CallEscape Sends an escape code to the GDI, using passed parameters. The syntax of an Escape call
- is:
- Escape(DC: hDC; Escape, Count: Integer; InData, OutData: Pointer): Integer
-
- where DC is the selected device context, Escape is the escape code, count is the number
- of bytes in InData, and outData is the data structure to receive data from the escape call,
- if requested. The function returns an integer value that is positive if the escape call was
- successful, zero if escape is not implemented, and negative if an error occurred. This
- method centralizes the escape calls to allow errors resulting from the calls to be handled
- from one location. Most errors occur on a NewFrame boundary, which signifies the end
- of a page.
-
- ClearEnv Clears the device's environment. This forces the printer driver to read the current printer
- settings from the WIN.INI file.
-
- DCcreated Creates a device context for the printer by calling the CreateDC method. CreateDC
- returns a word value greater than 0 if the call was successful.
-
- DeleteContext Deletes the device context created for the printer.
-
- DeviceName Returns the value of the Device instance variable.
-
- DocAbort Sends the ABORTDOC escape code. This code terminates the current job and erases
- everything the application has written to the device since the last ENDDOC code. This
- code is normally used to terminate print jobs that have not implemented an abort
- procedure, or those that have not reached their first NewFrame escape call. If a print
- job terminates due to cancellation or an error, this call should not be used. The GDI
- automatically terminates print jobs under these circumstances. If the application has
- created a cancellation dialog, the ABORTDOC code must be sent before the dialog box
- is destroyed, and before freeing an abort procedure-instance.
-
- Done Destructor method. Calls the parent (tObject) destructor.
-
- DoNewFrame Sends the NEWFRAME escape code to Windows. This code lets the printer know that
- the application has finished writing to a page. It causes a form feed to be issued. The
- NEWFRAME call restores the default values of the device context. If a font other than
- the default font has been selected, that font must be reselected after the NEWFRAME
- Escape.
-
- DraftModeOff Turns the printer draft mode off by sending the DRAFTMODE escape code. This
- method illustrates the use of the InData structure, sending a word value indicating the
- desired state of the draft mode. The value is passed in the high portion of the word. A
- value of 0 turns draft mode off, 01 turns it on. The draft mode of the printer can only
- be changed at page boundaries, such as after a NEWFRAME escape call.
-
- DraftModeOn Turns the printer draft mode on by sending the DRAFTMODE escape code. This
- method illustrates the use of the InData structure, sending a word value indicating the
- desired state of the draft mode. The value is passed in the high portion of the word. A
- value of 0 turns draft mode off, 01 turns it on. Since the value is passed in the high
- portion of the word, the value passed is 1000. In the method draftModeOff, the passed
- value is zero. The draft mode of the printer can only be changed at page boundaries,
- such as after a NEWFRAME escape call.
-
- DriverName Returns the value of the Driver instance variable.
-
- EndDocument Sends the ENDDOC Escape code to Windows. This signals that the current document
- has completed. If the print job has terminated abnormally, this method should not be
- called. In cases of abnormal termination, the GDI terminates the operation. If the
- application displays a print cancel dialog, the ENDDOC code must be sent before the
- dialog box is destroyed, and before freeing the procedure instance of an abort procedure.
- The ENDDOC or ABORTDOC escape calls should always be paired with the
- STARTDOC escape call.
-
- EndOfFile Ends the document. Causes a newPage, sends the ESCAPEDOC escape call, and deletes
- the printer device context.
-
- FlushPrn Sends the FLUSHOUTPUT escape code, which flushes the printer's output buffer.
-
- GetPrinterParms Retrieves the printer parameters from the WIN.INI file. The syntax for the call
- to GetProfileString is:
-
- GetProfileString(appName,keyName,default,RetunString: pChar; Size: Integer)
-
- where appName is the heading name to search for in the WIN.INI file, keyName is the
- key to search for under the heading, default is the default value if keyName is not found,
- ReturnString is the buffer in which the value of KeyName will be stored, and Size is the
- size of the buffer. The appName is usually 'windows', the keyName is usually 'device'.
-
- On returning from the call, ReturnString contains the name of the printer, the
- name of the printer driver and the port to which the printer is connected. These values
- are separated by commas. The returned values are copied to instance variables, since
- they are used by other methods in the object.
-
- Finally, there is another call to GetProfileString, this time searching for the
- keyName, 'spooler'. The value at this location is then used to set the boolean variable,
- noSpooler to true or false. This variable indicates whether the print spooler is active.
-
- Init Constructor method. Calls the parent (tObject) constructor.
-
- InitAbortProc Sends the SETABORTPROC escape code to initialize the abort procedure. The address
- for this procedure is passed in the procAddr variable. This illustrates the use of the
- InData data structure to send information to Windows. See the discussion about abort
- procedures, above, for more information.
-
- okPrint Returns true if the device context is greater than zero.
-
- PrinterPort Returns the value of the prnPort instance variable.
-
- prnDeviceMode This method displays the printer device driver dialog box, allowing the user to
- change the printer settings. This method has several variables:
-
- dHandle Handle of the load library for the current printer.
- drvName File name of the driver used to get dHandle.
- pAddr address of the procedure in the device DLL that will be called.
-
- A call to GetPrinterParms initializes the variables device and driver. Using the
- value in driver, a filename for the device driver is created by concatenating the extension
- '.drv' to the driver name. This is stored in the local variable, drvName. The call to
- LoadLibrary loads the device driver into memory, and returns a tHandle value that
- specifies the library module instance. If the value is less than 32, an error occurred.
- Note that in this version of the printer object, I am not trapping errors resulting from this
- call. The first call to GetProcAddress searches the DLL for a function named
- ExtDeviceMode. If that function is located, a tFarProc value is returned, representing
- the address of the function in the DLL. This function is present only in device drivers
- written for windows 3.0. If an address is returned, the ExtDeviceMode function is
- called, using the tGetExtDevMode function type as a template. The syntax for a call to
- ExtDeviceMode is:
-
- ExtDevMode(hWnd,hDriver,lpDevModeOutput,lpDeviceName,
- lpPort,lpDevModeInput,lpProfile,wMode)
-
- where hWnd is the parent window of the caller, hDriver is the device driver module,
- lpDevModeOutput is a tDevMode data structure. The driver will write the initialization
- information supplied in the lpDevModeInput parameter to this structure. lpDeviceName
- is the name of the printer device, lpPort is the port to which the printer is connected,
- lpDevModeInput is a tDevMode structure that supplies initialization information to the
- printer driver, lpProfile contains the name of a file with initialization information. If this
- parameter is nil, WIN.INI is used. wMode is a mask that determines what types of
- operations the function will perform. If wMode is 0, the call to the function returns the
- number of bytes required by the printer device driver structure. Otherwise, this parameter
- must have one or more of the following values (multiple values should be OR'd
- together):
-
- dm_Copy Writes the printer driver settings to the tDevMode record passed
- in lpDevModeOutput.
-
- dm_Modify Modifies the printer driver settings to the values passed in the
- lpDevModeInput record.
-
- dm_Prompt Displays the device mode dialog box, and changes the printer
- settings to what the user specified
-
- dm_Update Updates the printer environment and the WIN.INI to reflect the
- changes made by the user to the printer settings.
-
- If you do not include dm_update in the call to DevMode, any changes made to
- the printer settings will be for the current session only, and will not affect other,
- concurrent sessions.
-
- If the value returned from the first call to GetProcAddress is nil, indicating that
- the driver was not written for Windows 3, a second call is made to GetProcAddress to
- get the address of the DeviceMode function. The DeviceMode function always updates
- the WIN.INI file when it's parameters are changed. The syntax for a call to DeviceMode
- is:
- DeviceMode()
- where
-
-
- The call to FreeLibrary releases the loaded library module, and any memory
- associated with it.
-
- PrnError Calls an error routine based on the value of msgNum. Each of the error routines has
- been coded separately to allow them to be overridden in descendant objects. The error
- routines are not listed here. Each one calls the messageBox routine, passing the address
- of the appropriate error string and dialog title. These strings are declared as constants
- (eMsg) at the start of the implementation section.
-
-
- USING TPRNDEVICE
-
- The tPrnDevice object is a formal object; that is, you should never create an instance of it. It's
- purpose is to manage the lower level interface between Windows, an application, and the device driver.
- The tPrinter object, discussed next should be instantiated instead. It provides the higher level interface
- between the application and the tPrnDevice object.
-
-
-
- THE TPRINTER OBJECT
-
- Instance Variables
- HInst Contains the application instance value passed from the calling application. This variable
- is used in the NewAbortProc method when the call to MakeProcInstance is made. See
- the discussion concerning abort procedures at the beginning of this document.
-
- LpAbortProc Receives the tFarProc value returned from the MakeProcInstance call in the
- NewAbortProc method.
-
- maxX Holds the maximum line length, in pixels. This variable is initialized in the Start
- method.
-
- maxY Holds the maximum page length, in pixels. This variable is initialized in the Start
- method.
-
- Metrics A tTextMetrics data structure. This structure contains information about the selected
- font. It include the average dimensions of the characters, the number of characters in the
- font and the character set on which the font is based. Text metrics are most often used
- to determine the line spacing of the printed output. In this unit, the height of a line is
- returned by the height method. The height is the sum of the tmHeight field, which is the
- height of each character cell, and the tmExternalLeading fields, which is the
- recommended spacing between the bottom of one character cell and the top of the next.
-
- OkToPrint This variable is used as a flag to determine whether various steps in the initialization
- process were completed successfully.
-
- posX Holds the horizontal position of the print head on a line, in pixels.
-
- posY Holds the vertical position of the print head on the page, in pixels.
-
- TheParent A pWindowsObject that is initialized in the Init method. This variable holds the parent
- window from which this routine was instantiated. It's value is used in the printDialog
- method to instantiate the print cancel dialog.
-
- TYPES
-
- tPrinter The printer object. This is the lowest-level object that should be instantiated to print
- under Windows. It is a descendant of the tPrnDevice object, which handles the lower
- level interface with Windows.
-
- tPrnDialog A descendant of tDialog. This is the print cancel dialog that appears when a print job
- is being spooled. Pressing the cancel button sets the unit variable UserAbort to true,
- causing the print job to be canceled.
-
-
- UNIT VARIABLES
-
- PrintDialog A pointer to a tPrnDialog. This variable is not an instance variable, since it must be
- accessible from the abortProc function. Since the AbortProc method has no 'knowledge'
- of the printer object, it would not be able to intercept a message from the dialog.
-
- UserAbort A global boolean variable that is set when the user presses cancel in the print dialog box.
- This variable is checked by the AbortProc function to see if the print job has been
- aborted. See the discussion of the Abort Procedure near the beginning of this document.
-
-
- UNIT METHODS
-
- AbortProc This function is a callback function, called by windows during a print job. If the user
- presses cancel in the Print Dialog box, this function notifies Windows that the print job
- had been canceled.
-
-
- TPRINTER METHODS
-
- CheckNewPage This method compares the value of posY (the vertical position of the print head
- on the page) with MaxY (the maximum page length). If posY > maxY, the newPage
- method is called.
-
- CheckStart This method is responsible for some of the initialization that takes place within the printer
- object. It's calls deal mainly with the interface between the application and the printer
- object. The initialization between the printer object and Windows is handled by the Start
- method. CheckStart is responsible for instantiating the print dialog and the abort
- procedure, and disabling mouse and keyboard input to the parent window.
-
- If these initializations are performed successfully, CheckStart then calls the
- beginDoc method, which sends the STARTDOC escape call to the GDI. If any of the
- Init calls fail, or if the document is not started, checkStart reverses those initializations
- that were successfully completed.
-
- DoNewFrame Calls the ancestor.doNewFrame method to force a form feed.
-
- Finish This method is called at the end of a print job. It calls the EndOfFile method and the
- stopPrinter method, and frees the procedure instance created for the abort procedure.
-
- Height Returns the line spacing for the selected font. This is the sum of the metrics.tmHeight
- and metrics.tmExternalLeading fields. See the discussion under metrics, above, for more
- information.
-
- Init The Init method calls the ancestor.Init method, and initializes several instance variables.
-
- LineWidth This method returns the width (line length) of the passed string, based on the currently
- selected font. This is done through a call to GetTextExtent, which returns a longInt
- value containing the height of the string in the high word, and the width of the string in
- the low word. The lineWidth method returns only the width of the string. This value
- is used in the print method to check if the length of the string currently being printed
- causes the current line length to exceed the width of the page. If so, the offending text
- is wrapped to the next line.
-
- NewAbortProc This method calls the makeProcInstance function to obtain a far pointer to an abort
- procedure, bound to the data segment of the current application instance. This value is
- then passed in the inData parameter of the SetAbortProc escape call. This function
- returns true if the escape call returns a value greater than zero.
-
- It is important to note that all this method does is pass a pointer to a function.
- It does not guarantee that the pointer is valid, or that the function itself is valid. For
- example, if the EXPORT statement is left off of the AbortProc declaration, the program
- will still run, but the cancel dialog box will not work.
-
- NewLine NewLine causes a line feed by setting the posX variable to 0, and incrementing the posY
- variable by the value returned by the height method.
-
- NewPage NewPage starts a new page by resetting the values of posX and posY, and calling the
- doNewFrame method.
-
- PageSize This method returns a tPoint type containing the size of the page in pixels. These values
- are obtained by two calls to the Windows GetDeviceCaps method. GetDeviceCaps
- allows you to determine the extent of the printer device text writing abilities. There are
- about 28 different queries that can be made, including the horizontal and vertical
- resolution (used here), the aspect ratios for line drawing, the number of fonts, and so on.
- The possible parameters for calls to this method are listed in the Window reference
- guide, under Device capabilities.
-
- Print This method calls the printString method to send a line of text to the printer. Before
- making this call, Print determines whether the line length has been exceeded, based on
- the current position of the print head and the width of the string to be printed. If the
- length has been exceeded, Print forces a new line. Note that the entire string is wrapped
- to the next line from the beginning. The string is then sent to the printer by a call to
- the printString method. If the printString call is successful, the value of posX is
- incremented by the width of the string. Under normal circumstances, print does not issue
- a line feed. The Print method is similar to the Write procedure in standard pascal, in
- that it does not advance to the next line.
-
- PrintDlg Creates the print dialog box, a modeless dialog present while the print job is in progress.
- The purpose of the dialog box is to allow the user to cancel a print job.
-
- PrintLine PrintLine is similar to the WriteLn procedure in standard Pascal. It prints a line of text,
- followed by a line feed. It does this by calling the print method, followed by the
- newLine method.
-
- PrintString PrintString sends a null-terminated string of text to the selected device context using the
- TextOut method. The TextOut method writes the character string using the currently
- selected font. It is called by the Print method.
-
- RemoveDlg Destroys the print dialog box and disposes of the printDialog pointer.
-
- ResetPos Sets the posX and posY values to 0, indicating the start of a new page.
-
- Start The start method takes care of initializing the printer object and its relation with
- Windows. It is responsible for obtaining a device context, initializing most of the
- instance variables, and calling the CheckStart method to complete the initialization. If
- checkStart is successful, Start returns true.
-
- StopPrinter This method re-enables the parent window, removes the print dialog box, and sets the
- OkToPrint variable to false.
-
- TextHeight Returns the value of the metrics.tmHeight field, which is the height of the character cell
- of the currently selected font.
-
- TextWidth Returns the average width of the characters in the currently selected character set.
-
- Using the tPrinter object
- The tPrinter object is the object to use in an application to obtain basic access to the printer. The
- sample program TestPrn1 illustrates a simple file printing program that uses this object. Tprinter handles
- the interface between an application and the tPrnDevice object. That object handles the interface between
- the tPrinter object and the GDI. By maintaining this separation, it becomes much easier to extend the
- functionality of either the tPrnDevice or the tPrinter. If you find that the two objects meet your basic
- printing needs, but you need more features than they offer, the correct way to add new features is to
- create descendant objects. You should avoid, as much as possible, modification of these parent objects.
-
-
- ===============================================
- SAMPLE PROGRAMS
- The TestPrn1 sample program
- This program allows you to print a file or display the device mode dialog for a printer. The
- application object is tTestApp, the main window object is tPrnWindow. The printer object is instantiated
- using the tPrnWindow instance variable aPrinter. The two methods that interest us are the setPrinter
- method and the filePrint method.
-
- SETPRINTER METHOD
-
- This method displays the device mode dialog. It consists of three lines:
- aPrinter := new(pPrinter,Init(hInstance,@self));
- aPrinter^.prnDeviceMode(hWindow);
- dispose(aPrinter,Done);
-
- The first line instantiates aPrinter as a printer object. The hInstance variable contains the current
- tTestApp instance. The @Self parameter is the tPrnWindow object. The second line calls the
- prnDeviceMode method of the printer object. The hWindow parameter contains the device context for
- the current tPrnWind. The third disposes of the printer object. In the printer object, the device mode call
- has been set to change the environment only for the current session.
-
-
- THE FILEPRINT METHOD
-
- The filePrint method first displays a dialog box to get the name of a file to print. If the file name
- is invalid, the method does nothing. (After all, this is to demonstrate printing!). Once a valid file name
- is received, we are ready to print. As in the SetPrinter method, an instance of the tPrinter object is
- created by the line
- aPrinter := new(pPrinter, Init(hInstance, @self)
- here, the hInstance represents the current instance of tTestApp. @self represent the tPrnWindow
- instantiated by tTestApp. The value of these two parameters will be used in the instantiation of the
- AbortProc method and the print dialog box. The next line calls the Start method:
- if aPrinter^.Start('PrnTest',hWindow) then ...
- here, 'PrnTst' is the document name that will be used to uniquely identify this document, and
- hWindow is the current device context (tPrnWindow). This function call must return true in order for
- printing to commence. If it returns false, an error message should display, indicating what problem
- occurred.
-
- Once the document has been started, the application can send continuous output to the printer.
- This is represented by the WHILE..DO loop, following the call to the Start method. This loop reads in
- the next line of text from the file, and calls the printLine method, passing a pointer to the string as a
- parameter.
-
- When the end of textFile has been reached, the Finish method is called to end the print job. This
- call results in the print buffer being flushed, and a NewFrame call to advance the page. Finally, the
- aPrinter variable is disposed, and the job is done.
-
- While the print job is in progress, you should notice several things. First, the parent window to
- which the print dialog belongs has been disabled. Mouse and keyboard input to that window have been
- inhibited. It is still possible to access other windows on the screen, but the only active portion of the
- print process is the cancel dialog box. Another thing to notice is that the printing does not start
- immediatly. In fact, for smaller files, printing won't start until you have returned to the application.
- This is because Windows and the print manager spool the output to disk or memory, prior to starting
- output. Finally, note that any changes you make to the printer parameters affect only the current print
- session (if the driver was written for Windows 3).
-
-
- THE REPORTPRINTER OBJECT
-
- The reportPrinter object descends from the tPrinter object. It does not modify any of tPrinter's
- methods. Rather, it adds some behaviors to tPrinter to change the physical appearance of a printed
- document. ReportPrinter adds user defined pagination, based on lines per page, and headings that are
- printed on the top of each page. In the full implementation of this object in another system, it also
- printed column headings, and a columnar report with totals.
-
- The point of the reportPrinter object is to illustrate how the behavior of an object is modified by
- a descendant. It is intended as an example, not a full implementation of an application.
-
-
- TREPORTPRINTER
-
- INSTANCE VARIABLES
-
- Heading1 Holds the first heading line.
- Heading2 Holds the second heading line.
- lineCount Tracks how many lines have been printed. This variable is used to determine when to
- advance to a new page. Note that, in this implementation, if a line is wrapped by the
- Print method, line count is not affected.
- maxLines Maximum number of lines per page. This variable is set in the Init method.
- pageCount Keeps track of the page number. This count is included in heading line 2.
- rDateTime Holds the run date and time of the report. This value is included in heading line 2.
-
-
- METHODS
-
- Init Calls the ancestor(tPrinter) Init method to set the application instance and parent values.
- Init then initializes several other of the reportPrinter instance variables.
-
- SetDefaults SetDefaults initializes the values of the two heading lines. Heading1 is set to the value
- of the passed parameter, heading2 is set to the run date and time by a call to
- setHeading2.
-
- SetHeading2 Initializes heading2 to the run date and time instance variable and the constant PAGE.
-
- SetPageNum Strings the current page count into the local variable pCount, then copies it into the
- proper position in heading2.
-
- printMainHeadings Calls setPageNum, then sends heading1 and heading2 to the printer.
-
- StartNewPage Page break. If the page is greater than zero, calls new page, then prints the headings.
- NewPage causes a form feed. In this version of the object, pageCount is initially set to
- zero. This routine does not issue a form feed for the first page. (I was running out of
- paper!)
-
- OutText Check lineCount against maxLines to see if it is time for a new page. If so,
- startNewPage is called. The text passed as a parameter is sent to the printer with the
- tPrinter.PrintLine method, and pageNum in incremented by 1.
-
- SetRunTime A method to get the current date and time, format them, and copy them to the rDateTime
- instance variable.
-
-
- SAMPLE PROGRAM TESTPRN2
- This application is an example of the use of the reportPrinter object. The majority of the code
- is identical to that in TestPrn1, so I will not repeat that discussion. One difference is that the
- tPrnWindow instance variable aPrinter is now declared to be of type reportPrinter. The other differences
- are in the instantiation of aPrinter in the body of the program, and the object methods that are called
- during execution.
-
- In the method filePrint, the init call for aPrinter now includes an addition parameter, that
- for the lines per page. This value sets the reportPrinter instance variable maxLines, which is checked
- each time the outText method is called. Next, the reportPrinter method setDefaults is called to initialize
- the headings. The default heading passes is simply the word heading. If a nil value is passes, an empty
- string will be printer for heading1. The second heading line will be the run date and time, and the page
- number. The start method is called to begin the document. As the file is read, text is sent to the
- reportPrinter method outText, rather that the printLine method as was done in the previous example.
- This is so reportPrinter can manage the lines per page. The balance of the execution is identical to the
- testPrn1 program.
-
-
- WINDOWS PRINTING TIPS
- Keep in mind that tPrinter handles text on a line basis; that is, an application sends ready to print
- lines to the print or printLine methods. Remember that these are printer objects. Their only purpose is
- to get information from the application to the printer. If the output must be formatted in a special
- manner, it should be done before the print or printLine methods are called. That is the technique used
- in the original implementation of reportPrinter. The reportPrinter object formatted the text in to columns,
- formatted the subtotals and totals received from other objects, and passed a complete line of text to the
- tPrinter object. The overriding reason for doing this is that you know for certain that if an error in
- formatting text occurs, it occurs before the line gets to the printer unit. It makes report creation and
- debugging infinitely easier. Remember also that object-oriented programming takes the black box concept
- several steps farther. Any object descended from the printer object should concern itself only with
- printing. Any tasks not required for formatting a line, or printing it out do not belong in a printer object.
-
- ENDIT
- I sincerely hope that these objects, examples and documentation prove useful to your quest for
- the perfect Windows application. I have learned a great deal about Windows programming while creating
- them. I look forward to corresponding with you on the Compuserve forum. Happy Computing!
- -Bob Galivan