![]() |
Languages »
C# »
Utilities
Intermediate
License: The Code Project Open License (CPOL)
Sending Passthrough - Commands to a PrinterBy m@uBypassing GDI+ to send Printer-Commands |
C# 1.0.NET 1.1, Win2K, WinXP, Win2003VS.NET2003, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
I was looking for a long time to send escape-sequences to a printer while printing with the normal System.Drawing.Printing objects. This can be useful if you want to send faxes and tell the fax-drive with an escape sequence where you want to send the fax. You can also print barcodes with it. Most solutions that I found were about printing the whole page with userdefined commands. Here's a very simple solution about How to use GDI+ for printing and still have the possibility of sending userdefined PrinterCommands.
The code is very simple. There are two classes.
The first class is called EscapePrintHelper and looks like this:
public class EscapePrintHelper
{
[DllImport("gdi32.dll", EntryPoint="Escape",
CharSet=CharSet.Auto, SetLastError=true)]
private static extern int Escape
(IntPtr Hdc, int nEscape, int ncount, IntPtr inData, IntPtr outData);
private const int PASSTHROUGH = 19;
private IntPtr Handle;
private Graphics graphics;
public EscapePrintHelper(Graphics Graphics)
{
graphics = Graphics;
Handle = Graphics.GetHdc();
Graphics.ReleaseHdc(Handle);
}
public bool SendPassThroughExt(string PassthroughData)
{
return sendPassThrough(PassthroughData,Handle);
}
private bool sendPassThrough(string Passthroughdata, IntPtr handle)
{
IntPtr grp = handle;
bool RetVal = false;
IntPtr pData = string2Global(Passthroughdata,true);
try
{
int id = Escape(grp,PASSTHROUGH,0,pData,IntPtr.Zero);
RetVal = id > 0;
}
finally
{
Marshal.FreeHGlobal(pData);
}
return RetVal;
}
public bool SendPassThrough(string PassthroughData)
{
bool RetVal = false;
IntPtr grp = graphics.GetHdc();
try
{
RetVal = sendPassThrough(PassthroughData, grp);
}
finally
{
graphics.ReleaseHdc(grp);
}
return RetVal;
}
private IntPtr string2Global(string Data, bool includeSize)
{
int l = Data.Length;
int offset = 0;
if (includeSize)
{
l+=2;
offset = 2;
}
IntPtr RetVal = Marshal.AllocHGlobal(l);
short s = (short)Data.Length;
byte[] buf = new byte[l];
if (includeSize)
{
buf[1] = (byte)(s >> 8);
buf[0] = (byte)s;
}
System.Text.Encoding.Default.GetBytes(Data,0,Data.Length,buf,offset);
for (int i = 0; i< buf.Length; i++)
{
Marshal.WriteByte(RetVal,i,buf[i]);
}
return RetVal;
}
}
This class allows me to bypass the printer. So you could use this class without the second class, which is only a derived PrintDocument class that has a method called SendPassThroughCommand.
public class EscapeEventArgs:EventArgs
{
private EscapePrintDocument doc;
public EscapePrintDocument Doc
{
get
{
return doc;
}
}
private EscapeEventArgs()
{
}
public EscapeEventArgs(EscapePrintDocument Doc)
{
doc = Doc;
}
}
public delegate void EscapeEventHandler(object sender, EscapeEventArgs e);
public class EscapePrintDocument:System.Drawing.Printing.PrintDocument
{
public event EscapeEventHandler AfterPrint;
private EscapePrintHelper commandSender;
private bool printing;
public void SendPassThroughCommand(string PassThroughCommand)
{
if (printing)
{
commandSender.SendPassThrough(PassThroughCommand);
}
else
{
commandSender.SendPassThroughExt(PassThroughCommand);
}
}
protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e)
{
printing = true;
commandSender = new EscapePrintHelper(e.Graphics);
try
{
base.OnPrintPage(e);
}
finally
{
printing = false;
}
}
protected virtual void onAfterPrint()
{
if (AfterPrint != null)
{
AfterPrint(this, new EscapeEventArgs(this));
}
}
protected override void OnEndPrint(PrintEventArgs e)
{
try
{
onAfterPrint();
}
finally
{
base.OnEndPrint (e);
}
}
}
Its usage is now really simple. Just create an EscapePrintDocument and print it. While printing, use the SendPassThroughCommand to send EscapeSequences or things like that:
private void TestPrint()
{
PrintDialog dlg = new PrintDialog();
EscapePrintDocument test = new EscapePrintDocument();
dlg.Document = test;
if (dlg.ShowDialog() == DialogResult.OK)
{
test.PrintPage +=new PrintPageEventHandler(test_PrintPage);
test.Print();
}
}
private void test_PrintPage(object sender, PrintPageEventArgs e)
{
EscapePrintDocument doc = sender as EscapePrintDocument;
EscapePrintHelper hlp = new EscapePrintHelper(e.Graphics);
SizeF pf = e.Graphics.MeasureString(textBox1.Text,new Font("Arial",12));
RectangleF rf = new RectangleF(new PointF(30,30),pf);
e.Graphics.DrawString("Blah!",new Font("Arial",12),Brushes.Black,rf);
if (doc != null)
{
// Telling the Fax - Driver where to Send the Fax
doc.SendPassThroughCommand
("\x1b[COMMAND]NUMMER YourFaxNumber\x1b[END COMMAND]");
}
e.HasMorePages = false;
}
This example is tested with TobitFax (if anybody knows that one:)).
If you wish to send Passthrough commands after the last page, you can add a handler to the AfterPrint event and send the command there.
I hope this example is useful for somebody. I know that the implementation is not perfect, especially for the string2Global method which I tried to implement with a struct first, but I couldn't make it work.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 8 May 2007 Editor: Deeksha Shenoy |
Copyright 2007 by m@u Everything else Copyright © CodeProject, 1999-2009 Web13 | Advertise on the Code Project |