2010-08-17 156 views
11

我有一個使用「打印到文件」生成的PCL文件。如何在c#中打印pcl文件?

什麼是以編程方式在C#中打印此文件的最佳方式。

(當然,我打印的打印機支持PCL)。

我知道,從我的提示可以通過調用打印:

copy filename.pcl //location/printername 

所以我猜想,我也可以做同樣的事情編程方式(使用複印件)。我不知道是否有一個更清潔的方式來做這個,比如使用PrintDocument。

需要注意的是,當我使用的PrintDocument:

var pd = new PrintDocument 
     { 
      DocumentName = @"filename.pcl"; 
      PrinterSettings = {PrinterName = @"\\location\printername"} 
     }; 


pd.Print(); 

我總是打印空白頁。

+2

DocumentName是打印作業的顯示名稱。與磁盤上的文件名無關。 – dthorpe 2010-08-17 21:44:26

回答

2

我們用每DLL導入下面的方法:

[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, IntPtr 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)] RawPrinter 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); 
2

對不起,已經這麼晚來這個問題,但我有一些代碼,將做的工作。這本來不是我寫的。我收到了另一位程序員的幫助網站的代碼,但我不記得哪一個。它的作品非常漂亮。這是創建一個dll的項目。要自己做,請選擇Create:/ Project/Class Library(在項目類型下選擇Visual C#)。

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.IO; 

namespace PrintRaw 
{ 
    public class RawFilePrint 
    { 
     // Structure and API declarions: 
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
     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, IntPtr 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); 

     // SendBytesToPrinter() 
     // When the function is given a printer name and an unmanaged array 
     // of bytes, the function sends those bytes to the print queue. 
     // Returns true on success, false on failure. 
     public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) 
     { 
     Int32 dwError = 0, dwWritten = 0; 
     IntPtr hPrinter = new IntPtr(0); 
     DOCINFOA di = new DOCINFOA(); 
     bool bSuccess = false; // Assume failure unless you specifically succeed. 

     di.pDocName = "RAW Document"; 
     di.pDataType = "RAW"; 

     if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 
     { 
      if (StartDocPrinter(hPrinter, 1, di)) 
      { 
       if (StartPagePrinter(hPrinter)) 
       { 
        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 
        EndPagePrinter(hPrinter); 
       } 
       EndDocPrinter(hPrinter); 
      } 
      ClosePrinter(hPrinter); 
     } 
     if (!bSuccess) 
     { 
      dwError = Marshal.GetLastWin32Error(); 
     } 
     return bSuccess; 
     } 

     public static bool SendFileToPrinter(string szPrinterName, string szFileName) 
     { 
     FileStream fs = new FileStream(szFileName, FileMode.Open); 
     BinaryReader br = new BinaryReader(fs); 
     Byte[] bytes = new Byte[fs.Length]; 
     bool bSuccess = false; 
     IntPtr pUnmanagedBytes = new IntPtr(0); 
     int nLength; 

     nLength = Convert.ToInt32(fs.Length); 
     bytes = br.ReadBytes(nLength); 
     pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); 
     Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength); 
     bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); 
     Marshal.FreeCoTaskMem(pUnmanagedBytes); 
     return bSuccess; 
     } 

     public static bool SendStringToPrinter(string szPrinterName, string szString) 
     { 
     IntPtr pBytes; 
     Int32 dwCount; 
     dwCount = szString.Length; 
     // Assume that the printer is expecting ANSI text, and then convert 
     // the string to ANSI text. 
     pBytes = Marshal.StringToCoTaskMemAnsi(szString); 
     SendBytesToPrinter(szPrinterName, pBytes, dwCount); 
     Marshal.FreeCoTaskMem(pBytes); 
     return true; 
     } 
    } 
} 

現在,使用此代碼,添加所產生的DLL作爲你的項目的引用,然後調用功能,你需要他們。下面是我在今天使用它的一些代碼:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.IO; 

namespace PclFontTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      string szPrinterName = @"\\printserver\LaserJet 2420"; 

      StreamReader sr = new StreamReader(@"C:\Fonts\US20HP.FNT"); 
      string line = (char)27 + "*c32545D"; 
      line += sr.ReadToEnd(); 
      line += (char)27 + "*c5F"; 

      PrintRaw.RawFilePrint.SendStringToPrinter(szPrinterName, line); 


     } 
    } 
} 

該程序從文件讀取PCL字體。它用代碼包裝字體,爲其分配32545的字體ID,然後調用dll函數SendStringToPrinter。

+0

我試圖發送一個完整的pcl文件到設置爲打印到文件的laserjet 4驅動程序,該文件的狀態只是說「錯誤 - 打印」 – Jeremy 2011-03-03 20:28:06

+1

我相信問題是您正在嘗試打印到文件。上面的代碼需要一個僅包含PCL代碼的文件,並且您希望將其直接發送到打印機,而不受窗口乾擾。換句話說,你似乎試圖打印文件,以便將已打印到文件的文件存檔。 – 2011-03-07 19:28:38