![]() |
![]() |
|
![]() |
Win32 API and Printers Print Directly to a Printer © 2002 Rick Kelly www.crooit.com Preface Libraries and forms (Paradox 9) presented are available as a download here. Paradox 8 is not supported although Paradox 7-32 surprisingly works. After downloading into the folder of your choice, make that folder :WORK: and run the included form for a demonstration. You'll need to run the form before opening it in design mode as it references table :PRIV:__PJobs that is created in the form's INIT event. (If running Paradox 10, or if the table doesn't get created properly, you should first run the BldSpool.ssl script prior to running the form.) Introduction Previous articles in this series:
There are times when using Paradox? reports just doesn't get the job done or you've got a PostScript or PCL file generated on another system that you wish to print. In both cases, sending raw print data directly to the printer and bypassing the Windows print driver gives you precise control of your printed output. To send data directly to the printer under Win32, the following steps need to be followed.
Referenced Win32 APIs Other referenced Win32 API's have been covered in earlier articles. Newly introduced methods are: StartDocPrinter( hPrn cLong, cLevel cLong, pDocInfo cLong) cLong [stdcall "StartDocPrinterA"] StartPagePrinter(hPrn cLong) cLong [stdcall] WritePrinter( hPrn cLong, pBuf cPtr, size cLong, pcWritten cPtr) clong [stdcall] EndPagePrinter(hPrn cLong) cLong [stdcall] EndDocPrinter(hPrn cLong) cLong [stdcall]hPrn - Handle to the printer cLevel = Level or type of printer information structure to return - always 1 for our use pDocInfo - pointer to document information structure pBuf - Printer data to send size - Size of pBuf pcWritten - Bytes written Direct access to Windows printers As there are several pieces of information that must be shared between our methods, we will create the following Record Type to keep everything in one place. Type W32DirectPrintInfo = Record Printer String DocumentName String DocumentContent String DocumentSpacing SmallInt DocumentSpacingAfter Logical DocumentFormFeed Logical DocumentFormFeedAfter Logical PrinterHandle LongInt ;Do not modify DocumentStructure LongInt ;Do not modify BytesWritten LongInt ;Do not modify endRecord endTypeWhere: Printer = Name of printer to write to. DocumentName = Name of our document or print job. DocumentContent = Raw printer data to send. DocumentSpacing = Option line spacing. If > 0, the number specified indicates how many carriage return/line feeds to insert in the data stream. DocumentSpacingAfter = True - After DocumentContent has been sent, False - Before. DocumentFormFeed = True if a form feed is to be inserted into data stream DocumentFormFeedAfter = True - After DocumentContent has been sent, False - Before PrintHandle = Windows printer handle DocumentStructure = Windows Document Information Level 1 Structure pointer BytesWritten = Total bytes sent to the spooler Constants referenced by our methods: Const ; ; Standard ASCII printer control ; cnLineFeed = 10 cnFormFeed = 12 cnCarriageReturn = 13 endConstWe'll use three methods to encapsulate all the Win32 API calls needed. method OpenPrinterDirect(var dpi W32DirectPrintInfo) Logical var loReturn Logical liAny LongInt stAny String liSize LongInt liReturn LongInt apAny Application endVar loReturn = False ; ; Get a handle to the printer and initialize our structure ; dpi.PrinterHandle = 0 dpi.BytesWritten = 0 dpi.DocumentSpacing = 0 dpi.DocumentSpacingAfter = True dpi.DocumentFormFeed = False dpi.DocumentFormFeedAfter = True liReturn = OpenPrinter(dpi.Printer,dpi.PrinterHandle,0) ; ; Check if a valid printer name was found ; switch case liReturn <> 1 : otherwise : ; ; Ensure we have a document name ; switch case dpi.DocumentName.isAssigned() = False : dpi.DocumentName = apAny.getTitle() switch case dpi.DocumentName.isBlank() : dpi.DocumentName = "Corel Paradox" endSwitch endSwitch ; ; Allocate memory for Document Info 1 structure ; ; Document Name Pointer LongInt ; Output File Name Pointer LongInt - zero ; Data Type Pointer LongInt ; dpi.DocumentName String + x'00' ; Data Type String - "RAW" + x'00' ; liSize = dpi.DocumentName.size() liAny = liSize + 17 dpi.DocumentStructure = GlobalAlloc(fromHex("0x40"),liAny) liAny = dpi.DocumentStructure + 12 MoveToMemory(dpi.DocumentStructure,liAny,4) MoveToMemory(liAny,dpi.DocumentName,liSize + 1) liAny = dpi.DocumentStructure + 13 + liSize MoveToMemory(dpi.DocumentStructure + 8,liAny,4) stAny = "RAW" MoveToMemory(liAny,stAny,4) liReturn = StartDocPrinter( dpi.PrinterHandle, 1, dpi.DocumentStructure) liReturn = StartPagePrinter(dpi.PrinterHandle) loReturn = True endSwitch return loReturn endMethod method WritePrinterDirect(var dpi W32DirectPrintInfo) Logical var loReturn Logical liAny LongInt liSize LongInt liReturn LongInt stControl String endVar loReturn = False stControl = blank() ; ; Check for any spacing ; switch case dpi.DocumentSpacing > 0 : for liAny from 1 to dpi.DocumentSpacing stControl = stControl + chr(cnCarriageReturn) + chr(cnLineFeed) endFor switch case dpi.DocumentSpacingAfter = True : dpi.DocumentContent = dpi.DocumentContent + stControl otherwise : dpi.DocumentContent = stControl + dpi.DocumentContent endSwitch endSwitch ; ; Check for a form feed ; switch case dpi.DocumentFormFeed = False : case dpi.DocumentFormFeedAfter = False : dpi.DocumentContent = chr(cnFormFeed) + dpi.DocumentContent otherwise : dpi.DocumentContent = dpi.DocumentContent + chr(cnFormFeed) endSwitch liSize = dpi.DocumentContent.size() liAny = 0 ; ; Send the data to the printer ; liReturn = WritePrinter( dpi.PrinterHandle, dpi.DocumentContent, liSize, liAny) dpi.BytesWritten = dpi.BytesWritten + liAny loReturn = (liReturn = 1) return loReturn endMethod method ClosePrinterDirect(var dpi W32DirectPrintInfo) Logical var liReturn LongInt endVar ; ; End printer session and release resources ; liReturn = EndPagePrinter(dpi.PrinterHandle) liReturn = EndDocPrinter(dpi.PrinterHandle) liReturn = ClosePrinter(dpi.PrinterHandle) liReturn = GlobalFree(dpi.DocumentStructure) return True endMethodExample: Output ten lines on two pages double spaced. Assume that PW32Prnt is opened for library PW32Prnt.lsl. var dpi W32DirectPrintInfo siLine SmallInt endVar dpi.Printer = "Your Windows Printer Name goes here" dpi.DocumentName = "Paradox Print Direct " switch case PW32Prnt.OpenPrinterDirect(dpi) = False : msgStop("Error","Cannot open printer for direct access") otherwise : setMouseShape(MouseWait) dpi.DocumentSpacing = 2 for siLine from 1 to 10 switch case siLine = 5 : dpi.DocumentFormFeed = True otherwise : dpi.DocumentFormFeed = False endSwitch dpi.DocumentContent = "Line " + strval(siLine) + " - This is a test for direct printing." PW32Prnt.WritePrinterDirect(dpi) endFor PW32Prnt.ClosePrinterDirect(dpi) setMouseShape(MouseArrow) endSwitch Conclusion We now have methods that provide direct access to Windows printers. Next: Changing Printer Attributes Discussion of this article |
![]() Feedback | Paradox Day | Who Uses Paradox | I Use Paradox | Downloads ![]() |
|
![]() The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation. Paradox is a registered trademark of Corel Corporation. ![]() |
|
![]() Modified: 15 May 2003 Terms of Use / Legal Disclaimer ![]() |
![]() Copyright © 2001- 2003 Paradox Community. All rights reserved. Company and product names are trademarks or registered trademarks of their respective companies. Authors hold the copyrights to their own works. Please contact the author of any article for details. ![]() |
![]() |
|