Как напечатать файл PCL в C #? - PullRequest
       42

Как напечатать файл PCL в C #?

12 голосов
/ 18 августа 2010

У меня есть файл PCL, который я сгенерировал с помощью «print to file».

Каков наилучший способ программной печати этого файла в C #?

(Конечно, если принтерЯ печатаю на поддержку PCL.)

Я знаю, что могу печатать, вызывая из приглашения:

copy filename.pcl //location/printername

Так что я мог бы предположить, что я мог бы сделать то же самое программно (используя копию) ... Интересно, есть ли более чистый способ сделать это, скажем, с помощью PrintDocument.

Обратите внимание, что когда я использую PrintDocument:

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

pd.Print();

, я всегда печатаю пустую страницу.

Ответы [ 3 ]

3 голосов
/ 21 сентября 2010

Извините, что опоздал на этот вопрос, но у меня есть код, который сделает эту работу. Это не было написано мной изначально. Я получил код с сайта помощи другого программиста, но не могу вспомнить, какой именно. Работает красиво. Вот проект, который создает DLL. Чтобы сделать это самостоятельно, выберите «Создать: / Проект / Библиотека классов» (выберите «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, затем вызывает функцию dll SendStringToPrinter.

2 голосов
/ 18 августа 2010

Мы используем следующие методы для импорта 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 голосов
/ 18 августа 2010

Эта статья относится к Visual Basic , но следовать ей достаточно просто, чтобы иметь возможность применить ее к C #, я думаю.В противном случае, я с удовольствием помогу вам с любыми проблемными деталями.

Если принтер находится в сети, вот небольшой забавный пример того, как напрямую с ним поговорить .Не уверен, что это также работает, если вы просто отправляете байты PCL на принтер.

...