2010-12-14 18 views
18

Zwykle po podłączeniu mojego notebooka Zebra LP 2844-Z do portu USB, komputer widzi go jako drukarkę i mogę drukować do niego z notatnika jak każda inna drukarka ogólna. Jednak moja aplikacja ma kilka funkcji kodów kreskowych. Moja aplikacja analizuje dane wejściowe i generuje ciąg znaków w pamięci ZPL. Jak wysłać te dane ZPL na moje urządzenie USB?Wysyłaj surową drukarkę ZPL do drukarki Zebra przez USB

Odpowiedz

14

Znalazłem jeszcze prostszy sposób zapisu na drukarce Zebra przez port COM. Poszedłem do panelu sterowania Windows i dodałem nową drukarkę. Dla portu wybrałem COM1 (port, do którego podłączono drukarkę). Użyłem sterownika drukarki "Generic/Text Only". Wyłączyłem bufor wydruku (standardowa opcja w preferencjach drukarki), a także wszystkie zaawansowane opcje drukowania. Teraz mogę po prostu wydrukować dowolny ciąg do tej drukarki i jeśli ciąg zawiera ZPL, drukarka renderuje ZPL dobrze! Nie ma potrzeby specjalnych "sekwencji startowych" ani takich zabawnych rzeczy. Yay dla prostoty!

+0

Mam dwa pytania. ** 1. ** Co rozumiesz przez * "wydrukowanie dowolnego ciągu znaków na tej drukarce" *? ** 2. ** Czy wyłączanie buforowania i zaawansowane opcje drukowania kolidują z innymi drukarkami? –

+1

Można wyłączyć buforowanie dla poszczególnych drukarek, więc wyłączenie bufora drukarki nie wpłynie na żadną inną drukarkę. "Drukuj dowolny ciąg znaków" oznacza, że ​​wszystko, co wyślę do drukarki w dowolny sposób, zostanie potraktowane przez drukarkę jako ZPL. Jeśli więc wysyłasz dane binarne (takie jak dokument Word lub PDF), drukarka Zebra zinterpretuje je jako śmieci. Jeśli wydruk pliku tekstowego i tekst w tym pliku zawiera prawidłowe instrukcje ZPL, drukarka zinterpretuje poprawne instrukcje ZPL i wyrenderuje etykietę. –

-1

Możesz użyć COM lub P/Invoke z .Net, aby otworzyć sterownik Winspool.drv i wysłać bajty bezpośrednio do urządzeń. Ale nie chcesz tego robić; zazwyczaj działa tylko na jedno urządzenie w jednej wersji jednego sterownika, z którym testujesz, i łamie wszystko. Weź to z długiego, bolesnego, osobistego doświadczenia.

Co chcesz zrobić, to uzyskać czcionkę kodu kreskowego lub bibliotekę, która rysuje kody kreskowe za pomocą zwykłych starych poleceń GDI lub GDI +; jest jeden dla .Net here. Działa to na wszystkich urządzeniach, nawet po tym, jak Zebra zmieni sterownik.

+0

Kiedy mówisz ... "co chcesz zrobić, to uzyskać czcionkę kodu kreskowego lub bibliotekę GDI ..." - to może nie być to, czego chce Jason. Być może chce wysłać surową ZPL, a nie grafikę do drukarki. – barrypicker

+1

Twoje informacje na temat drukowania kodów kreskowych za pomocą zebry nie wymagają takiego rozwiązania, ponieważ język Zebra ZPL zawiera różne rodzaje kodów kreskowych .. i dlatego podajesz kod, który chcesz, a następnie numer lub ciąg do wydrukowania. To nie jest tak skomplikowane ... ale nie wszystkie języki ZPL są tak jasne, tak jak ostrzeżenie to nie zostało poprawnie udokumentowane w tym języku ZPL, miałem dokumenty tylko raz, ale wciąż wiele marginesów na interpretację. (Nic dziwnego, że sprzedają również oprogramowanie, które pisze tylko makropolecenia ZPL, prosząc o zebrę, by wyjaśniła, nie ma potrzeby, aby chronić swoje produkty.). – user613326

7

Nie wspomniano języka, więc mam zamiar dać wam kilka kilka wskazówek, jak to zrobić z prostej Windows API w C

pierwsze, otworzyć połączenie z drukarką OpenPrinter. Następnie uruchom dokument o numerze StartDocPrinter o polu pDatatype o strukturze DOC_INFO_1 ustawionym na "RAW" - mówi to sterownikowi drukarki, aby nie kodował niczego, co trafia do drukarki, ale przekazuje je niezmienione. Użyj StartPagePrinter, aby wskazać pierwszą stronę, WritePrinter, aby wysłać dane do drukarki, i zamknij je po EndPagePrinter, EndDocPrinter i ClosePrinter po zakończeniu.

+0

Wygląda na to, że będzie dokładnie to, czego potrzebuję. Kiedy dostanę szansę na sprawdzenie tego w pełni, dam ci znać, jak dobrze to dla mnie działa. Dzięki! –

16

Znalazłem odpowiedź ... lub przynajmniej najłatwiejszą odpowiedź (jeśli jest ich wiele). Kiedy zainstalowałem drukarkę, zmieniłem jej nazwę na "Drukarka etykiet ICS". Oto, jak zmienić opcje zezwalające na przekazywanie komend ZPL:

  1. Kliknij prawym przyciskiem myszy "Drukarka etykiet ICS" i wybierz "Właściwości".
  2. Na karcie "Ogólne" kliknij przycisk "Preferencje drukowania ...".
  3. Na karcie "Ustawienia zaawansowane" kliknij przycisk "Inne".
  4. Upewnij się, że zaznaczono pole "Włącz tryb przejściowy".
  5. Upewnij się, że "Sekwencja początkowa:" to "$ {".
  6. Upewnij się, że "Koniec sekwencji:" to "} $".
  7. Kliknij przycisk "Zamknij".
  8. Kliknij przycisk "OK".
  9. Kliknij przycisk "OK".

W moim kodzie, po prostu muszę dodać "$ {" na początku mojego ZPL i "} $" do końca i wydrukować go jako zwykły tekst. Dotyczy to "sterownika Windows dla drukarki ZDesigner LP 2844-Z wersja 2.6.42 (kompilacja 2382)". Działa jak marzenie!

+0

Interesujące. Nie sądzę, że jest to standardowa funkcja sterownika, musi być specyficzna dla sterownika Zebry. –

+0

@mark, to podstawowa funkcja Windows, aby umieścić coś przed strumieniem, który zostanie wysłany do urządzenia. ZPL jest językiem drukarki i rzeczywiście jest charakterystyczne dla zebry. – user613326

+0

@ user613326, Nie mam już dostępu do drukarki Zebra, ale właśnie otworzyłem inny sterownik drukarki. Na karcie Zaawansowane nie ma przycisku "Inne" i nie mogłem znaleźć żadnych innych odniesień do trybu Passthrough.Więc nie, to nie jest "podstawowa funkcja Windows", jest to coś bardzo specyficznego dla tego sterownika. –

2

ZPL jest prawidłową drogą. W większości przypadków poprawne jest użycie sterownika, który pobiera polecenia GDI; jednak drukarki etykiet Zebra są szczególnym przypadkiem. Najlepszym sposobem drukowania na drukarce Zebra jest bezpośrednie generowanie ZPL. Zauważ, że aktualnym sterownikiem drukarki Zebra jest drukarka "zwykłego tekstu" - nie ma "sterownika", który mógłby zostać zaktualizowany lub zmieniony w tym sensie, w jakim myślimy o większości drukarek posiadających sterowniki. To tylko kierowca w absolutnym minimalistycznym sensie.

9

Visual Studio C# rozwiązanie (znaleziono na http://support.microsoft.com/kb/322091)

Krok 1.) Tworzenie klasy 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; 
    } 
} 

Krok 2.) Tworzenie formularza z pola tekstowego i przycisk (pole tekstowe będzie zawierało ZPL, aby wysłać w tym przykładzie). W przycisku kliknij przycisk dodaj kod ...

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

Dzięki temu rozwiązaniu możesz dostosować swoje ustawienia do konkretnych wymagań. Być może zakodować konkretną drukarkę. Być może wyprowadzić tekst ZPL dynamicznie, a nie z pola tekstowego. Cokolwiek. Być może nie potrzebujesz interfejsu graficznego, ale to pokazuje, jak wysłać ZPL. Twoje użycie zależy od Twoich potrzeb.

0

Spędziłem 8 godzin, aby to zrobić. To jest proste ...

ty powinien mieć kod tak:

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; 

to zmienić zmiennej zawartości od 3 (otwarty plik już istnieje) do 1 (utwórz nowy plik). Będzie działać na Windows 7 i XP.

0

zainstalować udostępnionej drukarki: \ localhost \ zebra Wyślij ZPL jako tekst, spróbuj najpierw z kopią:

kopia file.zpl \ localhost \ zebra

bardzo prosty, prawie bez kodowania.