HTML clipboardThis article has been excerpted
from book "Graphics Programming with GDI+".One reason for using GDI may be speed and familiarity with GDI or having more
control over the printer.
Until now we have been selecting objects such as fonts and lines and then
drawing on a page, which is then printed out. Keep in mind that all the fonts
you can use within the .NET environment have to be TrueType fonts. Before
TrueType came along, there was something called PCL (Printer Control Language),
also known as bitmap fonts. So what's the difference? you may ask. It's simple:
A PCL or bitmap font is made up of patterns of dots that represent each letter.
The problem is that a different PCL font was required for every size of letter
needed, such as 12, 14, and so on. Different PCL, fonts were needed even for
italic and bold versions! As you can imagine, it was necessary to have lots of
PCL fonts to maintain the flexibility we take for granted today.
TrueType fonts, on the other hand, are a lot more flexible. The reason is that
the fonts are mathematical representation of each letter rather than a pattern
of dots. If I decide I need a Times New Roman font at size 20, the font is
simply recalculated rather than just a different pattern of dots being loaded.
What happens if your printer does not support the TrueType font you have
selected? The only way to print it is to send what you want to print to the
printers as graphics, which can be time-consuming if you're creating large
printouts.
The code in Listing 14.3, you would be able to create detailed pages consisting
of multiple fonts and graphics. The nice thing is that they can all be created
by just sending text to the printer rather than using graphics command.
You may want to change the printer before you rest this code. The following line
of code specifies the printer:
PrintDirect.OpenPrinter (\\\\192.168.1.101\\hpl,
ref lhPrinter, 0);
LISTING 14.3: Using GDI print functionality in a managed application
//PrintDirect.cs
//shows how to write data directly to the
//printer using Win32 APIs.
//this code sends Hewlett-Packard PCL5 codes
//to the printer to print
//out a rectangle in the middle of the page.
using
System;
using
System.Text;
using
System.Runtime.InteropServices;
[StructLayout (LayoutKind.Sequential)]
public
struct DOCINFO
{
[MarshalAs (UnmangedType.LPWStr)]
public
string pDocName;
[MarshalAs (UnmangedType.LPWStr)]
public
string pOutputFile;
[MarshalAs (UnmangedType.LPWStr)]
public
string pDataType;
}
public
class PrintDirect
{
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long OpenPrinter (String pPrinterName,
ref
IntPtr phPrinter, int pDefault);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long StartDocPrinter (Int hPrinter,
int
Level, ref DOCINFO pDocInfo);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long StartPagePrinter (
IntPtr hPrinter);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long WritePrinter (IntPtr hPrinter,
string
data, int buf, ref
int pcWrittern);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long EndPrinter ( IntPtr
hPrinter);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long EndDocPrinter (IntPtr hPrinter);
[DllImport ("winspool.drv",
CharSet =CharSet.Unicode, ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
public
static extern
long ClosePrinter (IntPtr hPrinter);
}
public
static void
Main()
{
System.IntPtr lhPrinter =
new
System.IntPtr();
DOCINFO di = new DOCINFO();
int
pcWritten = 0;
string
st1;
//Text to
print with a form-feed character
st1= "This
is an example of printing "+
"directory to a printer\f";
di.pDocName="my test document";
di.pDataType="RAW";
//The "\xlb"
means an ASCII escape character
st1="\xlb*c600a6b0P\f";
//lhPrinter contains the handle for the printer opened
//IF lhPrinter is 0, then an error has occurred.
PrintDirect.OpenPrinter (\\\\192.168.1.101\\hp1,
ref
lhPrinter, 0);
PrintDirect.StartDocPrinter (lhPrinter, 1, ref
di);
PrintDirect.StartPagePrinter (lhPrinter);
try
{
//Moves the cursor 900 dots (3 inches at
//300 dpi) in from the left margin, and
//600 dots (2 inches at 300 dpi) down
//from the top margin
st1="\xlb*p900x600Y";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritten);
//Using the
print model commands for rectangle
//dimensions, "600a" specifies a rectangle
//with a horizontal size, or width, of 600 dots,
//and "6b" specifies a vertical
//size, or height, of 6 dots. "0P" selects the
//solid black rectangle area fill
st1="\xlb*c600a6b0P";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritten);
//Specifies
a rectangle with width of
//6 dots, height of 600 dots, and a
//Fill pattern of solid black
st1="\xlb*c6a600b0P";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritten);
//Moves the
current cursor position to
//900 dots from the left margin and
//1200 dots down from the top margin
st1="\xlb*p900x1200Y";
PrintDirect.WritePrinter(lhPrinter,
st1, st1.Length, ref pcWritten);
//Specifies
a rectangle with a width
//of 606 dots, a height of 6 dots, and a
//fill patter of solid balck
st1="\xlb*c606a6b0P";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritter);
//Move the current cursor position to 1500
//dots in from the left margin and
//600 dots down from the top margin
st1="\xlb*p1500x600Y";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritten);
//Specifies a rectangle with a width of 6 dots,
//a height of 600 dots, and a
//fill patter of solid black
st1="\xlb*c6a600b0P";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritter);
//Send a from-feed character to the printer
st1="\f";
PrintDirect.WritePrinter (lhPrinter,
st1, st1.Length, ref pcWritten);
}
catch
(Exception e)
{
Console.WriteLine (e.Message);
}
PrintDirect.EndPagePrinter
(lhPrinter);
PrintDirect.EndDocPrinter (lhPrinter);
PrintDirect.ClosePrinter (lhPrinter);
}
}
Using this code will enable us to drive a printer at its maximum output rate.