2010-12-14 299 views
18

Normalmente, cuando enchufo mi Zebra LP 2844-Z al puerto USB, la computadora lo ve como una impresora y puedo imprimir desde el bloc de notas como cualquier otra impresora genérica. Sin embargo, mi aplicación tiene algunas características de código de barras. Mi aplicación analiza algunas entradas y genera una cadena en memoria de ZPL. ¿Cómo enviaría estos datos de ZPL a mi dispositivo USB?Enviar raw ZPL a la impresora Zebra a través de USB

Respuesta

14

He encontrado una manera más fácil de escribir en una impresora Zebra a través de un puerto COM. Fui al panel de control de Windows y agregué una nueva impresora. Para el puerto, elegí COM1 (el puerto al que estaba conectada la impresora). Utilicé un controlador de impresora "Genérico/Sólo texto". Inhabilité la cola de impresión (una opción estándar en las preferencias de la impresora) y todas las opciones de impresión avanzadas. Ahora, puedo simplemente imprimir cualquier cadena a esa impresora y si la cadena contiene ZPL, ¡la impresora representa perfectamente la ZPL! No hay necesidad de "secuencias de inicio" especiales o cosas así de funky. ¡Yay por simplicidad!

+0

Tengo dos preguntas. ** 1. ** ¿Qué quiere decir con * "imprimir cualquier cadena a esa impresora" *? ** 2. ** ¿La inhabilitación del spooling y las opciones avanzadas de impresión interfieren con otras impresoras? –

+1

Puede deshabilitar el spooling por impresora, por lo que apagar la cola de impresión para esta impresora no afectará a ninguna otra impresora. "Imprimir cualquier cadena" significa que cualquier cosa que envíe a la impresora por cualquier medio será tratada por la impresora como ZPL. Entonces, si envía datos binarios (como un documento Word o un PDF), la impresora Zebra lo interpretará como basura. Si imprime un archivo de texto y el texto en ese archivo contiene declaraciones ZPL válidas, la impresora interpretará las declaraciones ZPL válidas y presentará una etiqueta. –

-1

Puede usar COM, o P/Invoke de .Net, para abrir el controlador Winspool.drv y enviar bytes directamente a los dispositivos. Pero no quieres hacer eso; esto normalmente funciona solo para el dispositivo en la versión del único controlador con el que se prueba y se rompe en todo lo demás. Toma esto de una larga y dolorosa experiencia personal.

Lo que quiere hacer es obtener una fuente de código de barras o una biblioteca que dibuje códigos de barras usando comandos simples antiguos GDI o GDI +; hay uno para .Net here. Esto funciona en todos los dispositivos, incluso después de que Zebra cambie el controlador.

+0

Cuando dices ... "lo que quieres hacer es obtener una fuente de código de barras o una biblioteca GDI ...": puede que eso no sea lo que quiere Jason. Quizás quiera enviar ZPL sin formato, no gráficos al dispositivo de la impresora. – barrypicker

+1

Para que su información para imprimir códigos de barras con zebra no requiera tal solución, ya que el lenguaje Zebra ZPL incluye varios tipos de códigos de barras ... por lo que debe dar un código para el que desea y luego el número o cadena para imprimir. No es tan complejo ... pero no todo el lenguaje ZPL es claro, solo como una advertencia, no está documentado adecuadamente este lenguaje ZPL, tuve los documentos una vez pero aún tengo muchos márgenes para la interpretación. (No es de extrañar ya que también venden software que solo escribe macro de ZPL, pidiendo a Zebra que aclare que no se debe proteger sus productos). – user613326

7

Usted no ha mencionado una lengua, así que voy a darle algunos algunos consejos de cómo hacerlo con la API de Windows directamente en C.

En primer lugar, abrir una conexión a la impresora con OpenPrinter. A continuación, inicie un documento con StartDocPrinter con el campo pDatatype de la estructura DOC_INFO_1 establecido en "RAW" - esto le indica al controlador de impresora que no codifique nada que vaya a la impresora, sino que lo transfiera sin modificaciones. Use StartPagePrinter para indicar la primera página, WritePrinter para enviar los datos a la impresora, y ciérrela con EndPagePrinter, EndDocPrinter y ClosePrinter cuando haya terminado.

+0

Esto parece que será exactamente lo que necesito. Cuando tenga la oportunidad de probar esto por completo, te dejaré saber qué tan bien funcionó para mí. ¡Gracias! –

16

Encontré la respuesta ... o al menos, la respuesta más fácil (si hay varias). Cuando instalé la impresora, cambié el nombre a "Impresora de etiquetas ICS". Aquí se explica cómo cambiar las opciones para permitir el paso de comandos ZPL:

  1. Haga clic derecho en "Impresora de etiquetas ICS" y seleccione "Propiedades".
  2. En la pestaña "General", haga clic en el botón "Preferencias de impresión ...".
  3. En la pestaña "Configuración avanzada", haga clic en el botón "Otro".
  4. Asegúrese de que haya una marca en el recuadro etiquetado como "Habilitar modo de paso".
  5. Asegúrate de que la "Secuencia de inicio:" es "$ {".
  6. Asegúrate de que la "Secuencia de finalización" es "} $".
  7. Haga clic en el botón "Cerrar".
  8. Haga clic en el botón "Aceptar".
  9. Haga clic en el botón "Aceptar".

En mi código, solo tengo que agregar "$ {" al comienzo de mi ZPL y "} $" hasta el final e imprimirlo como texto sin formato. Esto es con el "controlador de Windows para la impresora ZDesigner LP 2844-Z versión 2.6.42 (compilación 2382)". ¡Funciona de maravilla!

+0

Interesante. No creo que sea una característica de controlador estándar, debe ser específica para el controlador Zebra. –

+0

@mark, es una característica básica de Windows para poner algo en frente de la transmisión que se enviará al dispositivo. ZPL es el lenguaje de la impresora y es específico de cebra. – user613326

+0

@ user613326, ya no tengo acceso a una impresora Zebra pero acabo de abrir otro controlador de impresora. No hay un botón "Otro" en la pestaña Avanzado, y no pude encontrar ninguna otra referencia al Modo Passthrough.Entonces no, no es una "característica básica de Windows", es algo muy específico para este controlador. –

2

ZPL es la forma correcta de hacerlo. En la mayoría de los casos, es correcto usar un controlador que abstraiga los comandos de GDI; sin embargo, las impresoras de etiquetas Zebra son un caso especial. La mejor forma de imprimir en una impresora Zebra es generar ZPL directamente. Tenga en cuenta que el controlador de impresora real para una impresora Zebra es una impresora de "texto sin formato"; no hay un "controlador" que pueda actualizarse o modificarse en el sentido en que pensamos que la mayoría de las impresoras tienen controladores. Es solo un controlador en el sentido minimalista absoluto.

9

Visual Studio C# solución (que se encuentra en http://support.microsoft.com/kb/322091)

Paso 1.) Crear clase RawPrinterHelper ...

using System; 
using System.IO; 
using System.Runtime.InteropServices; 

public class RawPrinterHelper 
{ 
    // 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 = "My C#.NET RAW Document"; 
     di.pDataType = "RAW"; 

     // Open the printer. 
     if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 
     { 
      // Start a document. 
      if (StartDocPrinter(hPrinter, 1, di)) 
      { 
       // Start a page. 
       if (StartPagePrinter(hPrinter)) 
       { 
        // Write your bytes. 
        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 
        EndPagePrinter(hPrinter); 
       } 
       EndDocPrinter(hPrinter); 
      } 
      ClosePrinter(hPrinter); 
     } 
     // If you did not succeed, GetLastError may give more information 
     // about why not. 
     if (bSuccess == false) 
     { 
      dwError = Marshal.GetLastWin32Error(); 
     } 
     return bSuccess; 
    } 

    public static bool SendFileToPrinter(string szPrinterName, string szFileName) 
    { 
     // Open the file. 
     FileStream fs = new FileStream(szFileName, FileMode.Open); 
     // Create a BinaryReader on the file. 
     BinaryReader br = new BinaryReader(fs); 
     // Dim an array of bytes big enough to hold the file's contents. 
     Byte[] bytes = new Byte[fs.Length]; 
     bool bSuccess = false; 
     // Your unmanaged pointer. 
     IntPtr pUnmanagedBytes = new IntPtr(0); 
     int nLength; 

     nLength = Convert.ToInt32(fs.Length); 
     // Read the contents of the file into the array. 
     bytes = br.ReadBytes(nLength); 
     // Allocate some unmanaged memory for those bytes. 
     pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); 
     // Copy the managed byte array into the unmanaged array. 
     Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength); 
     // Send the unmanaged bytes to the printer. 
     bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); 
     // Free the unmanaged memory that you allocated earlier. 
     Marshal.FreeCoTaskMem(pUnmanagedBytes); 
     return bSuccess; 
    } 
    public static bool SendStringToPrinter(string szPrinterName, string szString) 
    { 
     IntPtr pBytes; 
     Int32 dwCount; 
     // How many characters are in the string? 
     dwCount = szString.Length; 
     // Assume that the printer is expecting ANSI text, and then convert 
     // the string to ANSI text. 
     pBytes = Marshal.StringToCoTaskMemAnsi(szString); 
     // Send the converted ANSI string to the printer. 
     SendBytesToPrinter(szPrinterName, pBytes, dwCount); 
     Marshal.FreeCoTaskMem(pBytes); 
     return true; 
    } 
} 

Paso 2.) crear un formulario con cuadro de texto y botón (cuadro de texto contendrá la ZPL para enviar en este ejemplo). En botón haga clic en evento agregar código ...

private void button1_Click(object sender, EventArgs e) 
     { 
      // Allow the user to select a printer. 
      PrintDialog pd = new PrintDialog(); 
      pd.PrinterSettings = new PrinterSettings(); 
      if (DialogResult.OK == pd.ShowDialog(this)) 
      { 
       // Send a printer-specific to the printer. 
       RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, textBox1.Text); 
       MessageBox.Show("Data sent to printer."); 
      } 
      else 
      { 
       MessageBox.Show("Data not sent to printer."); 
      } 
     } 

Con esta solución, puede modificar para cumplir con requisitos específicos. Quizás hardcode la impresora específica. Quizás derivar el texto de ZPL de forma dinámica en lugar de desde un cuadro de texto. Lo que sea. Tal vez no necesite una interfaz gráfica, pero esto muestra cómo enviar la ZPL. Su uso depende de sus necesidades.

0

Pasé 8 horas para hacer eso. Es simple ...

Usted SHAUD tienen un código de esa manera:

private const int GENERIC_WRITE = 0x40000000; 

//private const int OPEN_EXISTING = 3; 
private const int OPEN_EXISTING = 1; 
private const int FILE_SHARE_WRITE = 0x2; 
private StreamWriter _fileWriter; 
private FileStream _outFile; 
private int _hPort; 

cambio de que el contenido de la variable (archivo abierto ya existen) 3 a 1 (crear un nuevo archivo). Funcionará en Windows 7 y XP.

0

Instalar una cuota de su impresora: \ localhost \ cebra Enviar ZPL como texto, tratar con copia en primer lugar:

copia file.zpl \ localhost \ cebra

muy simple, casi sin la codificación.

Cuestiones relacionadas