Hi,
I would like to be able to print one line at a time using a network line
printer, without ejecting tha page each time one line has >been printed.
The PrintDocument object seems to support printing at page level only.
Does anyone have something to suggest >here? Older applications used to
send control characters to the printer in order to achieve this behavior.
Does a similar >technique apply here?
Yea, you'll want to print directly to the printer, not using GDI+.
This class should work for you.
-Michael
MVP
public class RawPrinter {
#region Win32
[StructLayout(LayoutKind.Sequential)]
public class DOCINFOA {
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true,
CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)]
string szPrinter, out IntPtr hPrinter, long pd);
[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="StartDocPrinterA",
SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool StartDocPrinter( IntPtr hPrinter, Int32 level,
[In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint="EndDocPrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="StartPagePrinter",
SetLastError=true, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes,
Int32 dwCount, out Int32 dwWritten );
[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern Int32 GetLastError();
#endregion
private static bool SendBytesToPrinter(string szPrinterName, IntPtr
pBytes, Int32 dwLength) {
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
int MAX_DATA = 2000;
di.pDocName = "Receipt";
di.pDataType = "RAW";
while (dwLength > 0) {
// Open the printer.
if (OpenPrinter(szPrinterName, out hPrinter, 0)) {
// Start a document.
if (StartDocPrinter(hPrinter, 1, di)) {
// Start a page.
if (StartPagePrinter(hPrinter)) {
// Write your bytes.
bSuccess = WritePrinter(
hPrinter,
pBytes,
(dwLength > MAX_DATA)?MAX_DATA:dwLength,
out dwWritten);
if (!bSuccess) {
// could not print the receipt
return false;
}
pBytes = (IntPtr)(pBytes.ToInt32() + dwWritten);
dwLength -= dwWritten;
EndPagePrinter(hPrinter);
} else {
// could not start a page
return false;
}
EndDocPrinter(hPrinter);
} else {
// could not start a doc
return false;
}
ClosePrinter(hPrinter);
} else {
// could not open the printer
return false;
}
if (dwLength > 0) {
System.Threading.Thread.Sleep(10000);
}
}
// If you did not succeed, GetLastError may give more information
// about why not.
if( bSuccess == false ) {
dwError = GetLastError();
}
return bSuccess;
}
public static void SendStringToPrinter(string szPrinterName, string
szString) {
// print the stuff on a new thread
RawPrinter rp = new RawPrinter(szPrinterName, szString);
rp.Start();
}
private Thread spirit;
private string szPrinterName, szString;
private RawPrinter(string szPrinterName, string szString) {
this.szPrinterName = szPrinterName;
this.szString = szString;
spirit = new Thread(new ThreadStart(PrintOut));
spirit.IsBackground = true;
}
public void Start() {
spirit.Start();
}
private void PrintOut() {
IntPtr pBytes;
Int32 dwLength;
// How many characters are in the string?
dwLength = szString.Length;
// Convert to ANSI string and allovcate in unmanaged heap
pBytes = Marshal.StringToHGlobalAnsi(szString);
// Send the converted ANSI string to the printer.
SendBytesToPrinter(szPrinterName, pBytes, dwLength);
// free the converted string
Marshal.FreeHGlobal(pBytes);
}
}