How do I print a PCL file in C#?

前端 未结 3 1774
时光说笑
时光说笑 2021-02-05 18:18

I have a PCL file that I generated using \"print to file\".

What\'s the best way to programmatically print this file in C#?

(Given of course that the printer I a

3条回答
  •  抹茶落季
    2021-02-05 18:56

    I'm sorry to have come so late to this question, but I have some code that will do the job. It was not written by me originally. I received the code from another programmer's help site, but I can't remember which one. It works beautifully. Here is the project, which creates a dll. To do it yourself, select Create:/Project/Class Library (select Visual C# under project types).

    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;
          }
       }
    }
    

    Now, to use this code, add the resulting dll as a reference to your project, then call the functions as you need them. Here is some code where I used it, just today:

    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);
    
    
            }
        }
    }
    

    This program reads a PCL Font from a file. It wraps the font with code to assign a font id of 32545 to it, then calls the dll function SendStringToPrinter.

提交回复
热议问题