Three Methods to Send Preformatted Files Directly to Printer

Last reviewed: June 21, 1995
Article ID: Q119113
The information in this article applies to:
  • Standard and Professional Editions of Microsoft Visual Basic for Windows, versions 2.0 and 3.0

SUMMARY

This article discusses three methods for sending data or a preformatted file directly to the printer, thus bypassing the Windows printer driver:

  • Using the Windows API Escape() with PASSTHROUGH

    -or-

  • Using the Windows API SpoolFile()

    -or-

  • Opening the printer port for binary file access

MORE INFORMATION

Applications written for Windows version 3.1 can use either the SpoolFile() function or the PASSTHROUGH printer escape to send a printer-specific file to Print Manager for spooling to a printer. In addition, Visual Basic allows you to open the printer port (lpt1, lpt2, etc.) as an MS-DOS device and send data directly to it. The following sections discuss each method.

Using the Windows API Escape() with PASSTHROUGH

Overall, the Escape() API works well. The major drawback is that not all printer drivers support it because it is considered obsolete. For additional information on how to implement this function, please see the following article in the Microsoft Knowledge Base:

ARTICLE-ID: Q96795

TITLE     : Using PASSTHROUGH Escape to Send Data Directly to Printer

Using the Windows API SpoolFile()

The SpoolFile function puts a file into the spooler queue. This is useful when you have large files to print and you do not want to have your program handle all of the printing. The following is a list of known limitations of the Windows SDK SpoolFile() function:

  • SpoolFile() is documented as being for use with local printers only. Using SpoolFile() with network printers results in undefined behavior; sometimes you may get output, sometimes you may get a general protection fault (GPF).
  • Print Manager must be enabled (in the Printer Control Panel dialog box) for you to use SpoolFile().
  • Print Manager treats the file exactly as it treats temporary files generated through "normal" GDI printing. This has two major effects:

    - The file must use the correct language/format for the printer. Print

         Manager does not attempt to interpret or modify the file in any way,
         but simply writes the contents to the port.
    

    - Print Manager deletes the file when done spooling it to the port.

  • Finally, a bug in SpoolFile() causes Print Manager to cause a GPF when the application that called SpoolFile() terminates before Print Manager is done spooling the file to the port.

Despite these limitations, the API SpoolFile() is convenient and simple to use. Remember that SpoolFile() treats the file you send to it just like any other temporary file and deletes it when done. Therefore, if you need to preserve the file you want to print, you need to copy it. The code below provides an example of calling SpoolFile().

Before you run this sample, you need to have a preformatted file to print. You can create this by printing a document from Word and choosing the Print to File option. This sample assumes that C:\TMP\DATA.PRN is the file you want to print.

  1. Start a New Project in Visual Basic; form1 is created by default.

  2. Place the following declarations in the General Declarations section of the form (each declaration needs to be on one line of code):

    Declare Function SpoolFile Lib "GDI" (ByVal lpszPrinter As String,
                                          ByVal lpszPort As String,
                                          ByVal lpszJob As String,
                                          ByVal lpszFile As String)
                                          As Integer
    
    Declare Function GetProfileString Lib "Kernel" (ByVal lpAppName As String,
                                                ByVal lpKeyName As String,
                                                ByVal lpDefault As String,
                                                ByVal lpReturnedString As
                                                                       String,
                                                ByVal nSize As Integer)
                                                As Integer
    
    

  3. Add a command button (Command1) to the form and place the following code in the Click() event:

       Sub Command1_Click ()
    
       Dim DefaultPrinter As String  'hold the default printer information
       Dim Driver As String          'holds driver name
       Dim Port As String            'holds printer port of driver
       Dim FileToSpool As String     'name of file we are going to print
       Dim ret As Integer            'return value of API calls
    
       'initialize our printer buffer, call the API, and trim the Nulls
       DefaultPrinter = Space$(128)
    
       'the following statement needs to be on one line of code
       ret = GetProfileString("windows", "device", "NONE", DefaultPrinter,
       Len(DefaultPrinter))
    
       DefaultPrinter = Left$(DefaultPrinter, ret)
    
       'parse the printer line
       'for the port, look for the second comma, this is where the port is
       'for the printer driver, take the string up to the first comma
       Driver = Left$(DefaultPrinter, InStr(DefaultPrinter, ",") - 1)
       Port = Mid$(DefaultPrinter, InStr(Len(Driver) + 2, DefaultPrinter, ",")
       + 1)
    
       'copy our data file and print the copy - SpoolFile will DELETE it!
       FileToSpool = "c:\tmp\toprintr.prn"
       FileCopy "c:\tmp\data.prn", FileToSpool     'the data file is data.prn
    
       'spool the file to the PrintManager
       ret = SpoolFile(Driver, Port, App.Title & "-Spooling File", FileToSpool)
    
       'check for errors (values in the Win 3.1 SDK help file
       If ((ret < -5) Or (ret > 0)) And (ret <> &H4000) Then
           MsgBox "File Spooled-Don't Quit until PrintManager is done
       printing!"
       Else
           MsgBox "Error on print: (" & CStr(ret) & ")"
       End If
       End Sub
    
    

  4. When you run the program and choose the command button, the program will print the file C:\TMP\DATA.PRN to the default printer.

Opening the Printer Port for Binary File Access

Using this method is much the same as implementing printer escape sequences in a Visual Basic for MS-DOS or QBasic applications. The advantages and disadvantages of this method are listed below:

  • No Windows API functions are used.
  • This method prints to the MS-DOS device LPTx, which can be redirected by your network.
  • Your program handles all the printing.
  • This method is not supported under Windows NT.

Below is a sample program that opens an input file and the printer port, "lpt1", for binary file access. The program then grabs an 8K chunk of data from the input file and sends it directly to the printer, looping until it reaches the end of file.

  1. In Visual Basic, start a new project; form1 is created by default.

  2. Add a command button (Command1) to the form, and place the following code in the click event:

          Sub Command1_Click ()
    
          Const MaxSize = 8192     'max buffer size
    
          Dim Chunk As String      'buffer to hold data
          Dim numLoops As Long     'number of 8k loops
          Dim LeftOver As Integer  'amount of file left
          Dim i As Integer         'counter for loops
    
          'open our datafile and printer port
          Open "c:\tmp\data.prn" For Binary As #1
          Open "lpt1" For Binary As #2
    
          'calculate size of file and amount left over
          numLoops = LOF(1) \ MaxSize
          LeftOver = LOF(1) Mod MaxSize
    
          'initialize variables and loop
          Chunk = Space$(MaxSize)
          For i = 1 To numLoops
              Get #1, , Chunk
              Put #2, , Chunk
          Next
    
          'grab what's leftover
          Chunk = Space$(LeftOver)
          Get #1, , Chunk
          Put #2, , Chunk
    
          'close all our open files
          Close #2
          Close #1
          End Sub
    
    

  3. Press F5 to run the program and it prints out the file C:\TMP\DATA.PRN for you.

REFERENCES

See the following Microsoft Knowledge Base article from the WinSDK database:

     ARTICLE-ID: Q111010
     TITLE     : INF: An Alternative to SpoolFile()


Additional reference words: 3.00 spool
KBCategory: kbprint kbprg kbcode
KBSubcategory: APrgPrint


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: June 21, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.