Recipe 11.2. Sending


Recipe 11.2. Sending "Raw" Data to a Printer

Problem

You need to send unprocessed data directly to a printer or print spooler, without processing by a printer driver.

Solution

Sample code folder: Chapter 11\RawPrinterData

The .NET Framework does not include direct support for this type of "raw" printing, so create your own class that uses various Win32 API calls.

Discussion

The .NET Framework does not include support for "raw" printing, the ability to send your own custom data directly to the printer. Some printers, such as barcode and receipt printers, accept data with embedded "escape sequences" that control the output on the printer. Many of these older printers do not include Windows drivers and can only be used in raw mode.

To print to these printers from .NET, you must use a DLL commonly used in Visual Basic 6.0 development to send raw data and perform other low-level operations on printers. The winspool.drv library includes several useful printer-specific functions, including functions that let you open a channel to the printer directly and send raw data. Because this library is not a .NET library, you have to coax .NET through the communication process using the various options to the DllImport attribute that you attach to each library-call definition.

The following code references the relevant public functions in this library and uses them to connect to the printer and send the requested data:

 Imports System.Runtime.InteropServices Public Class RawPrinter    ' ----- Define the data type that supplies basic    '       print job information to the spooler.    <StructLayout(LayoutKind.Sequential, _        CharSet:=CharSet.Unicode)> _    Public Structure DOCINFO       <MarshalAs(UnmanagedType.LPWStr)> _          Public pDocName As String       <MarshalAs(UnmanagedType.LPWStr)> _          Public pOutputFile As String       <MarshalAs(UnmanagedType.LPWStr)> _          Public pDataType As String    End Structure    ' ----- Define interfaces to the functions supplied    '       in the DLL.    <DllImport("winspool.drv", EntryPoint:="OpenPrinterW", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function OpenPrinter( _       ByVal printerName As String, ByRef hPrinter As IntPtr, _       ByVal printerDefaults As Integer) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="ClosePrinter", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function ClosePrinter( _       ByVal hPrinter As IntPtr) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="StartDocPrinterW", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function StartDocPrinter( _       ByVal hPrinter As IntPtr, ByVal level As Integer, _       ByRef documentInfo As DOCINFO) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="EndDocPrinter", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function EndDocPrinter( _       ByVal hPrinter As IntPtr) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="StartPagePrinter", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function StartPagePrinter( _       ByVal hPrinter As IntPtr) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="EndPagePrinter", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function EndPagePrinter( _       ByVal hPrinter As IntPtr) As Boolean    End Function    <DllImport("winspool.drv", EntryPoint:="WritePrinter", _       SetLastError:=True, CharSet:=CharSet.Unicode, _       ExactSpelling:=True, _       CallingConvention:=CallingConvention.StdCall)> _    Public Shared Function WritePrinter( _       ByVal hPrinter As IntPtr, ByVal buffer As IntPtr, _       ByVal bufferLength As Integer, _       ByRef bytesWritten As Integer) As Boolean    End Function    Public Shared Function PrintRaw( _          ByVal printerName As String, _          ByVal origString As String) As Boolean       ' ----- Send a string of   raw data to   the printer.       Dim hPrinter As IntPtr       Dim spoolData As New DOCINFO       Dim dataToSend As IntPtr       Dim dataSize As Integer       Dim bytesWritten As Integer       ' ----- The internal format of a .NET String is just       '       different enough from what the printer expects       '       that there will be a problem if we send it       '       directly. Convert it to ANSI format before       '       sending.       dataSize = origString.Length()       dataToSend = Marshal.StringToCoTaskMemAnsi(origString)       ' ----- Prepare information for the spooler.       spoolData.pDocName = "My Visual Basic .NET RAW Document"       spoolData.pDataType = "RAW"       Try          ' ----- Open a channel to   the printer or spooler.          Call OpenPrinter(printerName, hPrinter, 0)          ' ----- Start a new document and Section 1.1.          Call StartDocPrinter(hPrinter, 1, spoolData)          Call StartPagePrinter(hPrinter)          ' ----- Send the data to the printer.          Call WritePrinter(hPrinter, dataToSend, _             dataSize, bytesWritten)          ' ----- Close everything that we opened.          EndPagePrinter(hPrinter)          EndDocPrinter(hPrinter)          ClosePrinter(hPrinter)       Catch ex As Exception          MsgBox("Error occurred: " & ex.ToString)       Finally          ' ----- Get rid of the special ANSI version.          Marshal.FreeCoTaskMem(dataToSend)       End Try    End Function End Class 

This class includes all shared members, so just call them directly without creating an instance. Use the PrintRaw method by passing it a printer name and raw data to send:

 RawPrinter.PrintRaw("MyPrinter", _    "Hello, this is a test." & vbCrLf) 

You can use this to send data to network printers by supplying a printer path in the format \\SystemName\PrinterName.

See Also

The code in this recipe is based on a Microsoft-supplied Knowledge Base article. On the MSDN web site (http://msdn.microsoft.com), access article number 322090 for additional details on using the winspool.drv file from .NET.




Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net