C# Печать ZPL на принтере Zebra Из приложения WPF

#c# #wpf #printing #zpl

Вопрос:

У меня есть приложение C# WPF, которое должно печатать этикетки с принтера Zebra. Принтер Zebra настроен как универсальный текстовый принтер (в отличие от использования драйвера Zebra/другого). ZPL-код этикетки уже сгенерирован, и когда я печатаю ZPL-код из текстового редактора, такого как Блокнот или Notepad , этикетка печатается отлично. Когда я печатаю одну и ту же строку из своего приложения WPF, я получаю разные результаты.

Что может быть причиной различных результатов диссертаций? Я несколько раз проверял и повторно копировал код ZPL в свое приложение, поэтому я вполне уверен, что ZPL тот же самый. Существует ли лучший способ печати с помощью приложений C# WPF? Идея состоит в том, чтобы позволить пользователю настроить принтер Zebra как стандартный принтер Windows и выбрать его во время печати из журнала печати.

Вот мой код для печати:

         System.Windows.Controls.PrintDialog prnt = new PrintDialog();            
        prnt.PageRangeSelection = PageRangeSelection.AllPages;
        prnt.UserPageRangeEnabled = false;                        

        Nullable<bool> result = prnt.ShowDialog();

        if (result == true)
        {

            string zpl = "^XA"   Environment.NewLine  
                "^RS,,,3,N,,,2"   Environment.NewLine  
                "^RR3"   Environment.NewLine  
                "^XZ"   Environment.NewLine  
                "^XA"   Environment.NewLine  
                "^SZ2^JMA"   Environment.NewLine  
                "^MCY^PMN"   Environment.NewLine  
                "^PW459"   Environment.NewLine  
                "^LT41"   Environment.NewLine  
                "~JSN"   Environment.NewLine  
                "^MD30"   Environment.NewLine  
                "^JZY"   Environment.NewLine  
                "^LH0,0^LRN"   Environment.NewLine  
                "^XZ"   Environment.NewLine  
                "^XA"   Environment.NewLine  
                "^FT31,42"   Environment.NewLine  
                "^CI0"   Environment.NewLine  
                "^A0N,23,31^FDAsset ID:^FS"   Environment.NewLine  
                "^FT31,74"   Environment.NewLine  
                "^A0N,23,31^FDA0000001^FS"   Environment.NewLine  
                "^FT31,106"   Environment.NewLine  
                "^A0N,23,31^FDItem Code:^FS"   Environment.NewLine  
                "^FT31,137"   Environment.NewLine  
                "^A0N,23,31^FD500124^FS"   Environment.NewLine  
                "^FT49,324"   Environment.NewLine  
                "^A0N,23,31^FDShuttleworth conveyor^FS"   Environment.NewLine  
                "^FT49,346"   Environment.NewLine  
                "^A0N,23,31^FDnylon rollers - A^FS"   Environment.NewLine  
                "^FT49,369"   Environment.NewLine  
                "^A0N,23,31^FDsection of roller is 4-1/2^FS"   Environment.NewLine  
                "^FT49,392"   Environment.NewLine  
                "^A0N,23,31^FDlong with a deep pocket...^FS"   Environment.NewLine  
                "^FT31,172"   Environment.NewLine  
                "^A0N,23,31^FDMfgr Part:^FS"   Environment.NewLine  
                "^FT31,202"   Environment.NewLine  
                "^A0N,23,31^FD701646-231A^FS"   Environment.NewLine  
                "^FT31,254"   Environment.NewLine  
                "^A0N,23,31^FDStore:^FS"   Environment.NewLine  
                "^FT258,254"   Environment.NewLine  
                "^A0N,23,31^FDBin:^FS"   Environment.NewLine  
                "^FT31,289"   Environment.NewLine  
                "^A0N,23,31^FDB5 Maint^FS"   Environment.NewLine  
                "^FT258,289"   Environment.NewLine  
                "^A0N,23,31^FDE6B^FS"   Environment.NewLine  
                "^FO258,23"   Environment.NewLine  
                "^BY1^BCN,38,N,N^FD>:A0>5000001^FS"   Environment.NewLine  
                "^FO258,87"   Environment.NewLine  
                "^BCN,38,N,N^FD>;500124^FS"   Environment.NewLine  
                "^RFW,H,1,2,1^FD1400^FS"   Environment.NewLine  
                "^RFW,H,2,4,1^FDA0000001^FS"   Environment.NewLine  
                "^PQ1,0,1,Y"   Environment.NewLine  
                "^XZ"   Environment.NewLine;

            var doc = new FlowDocument();
            doc.ColumnWidth = prnt.PrintableAreaWidth;

            Paragraph p = new Paragraph();
            p.Inlines.Add(zpl);
            doc.Blocks.Add(p);
            prnt.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "Label A0000001");

            //doc.Blocks.Add(new Paragraph(new Run(zpl)));
            //prnt.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "Label A0000001");
            //prnt.PrintDocument((Section)XamlReader.Parse(zpl));                 
            
        }
 

Вот результаты печати этикеток из текстового редактора (слева) и моего приложения (справа):
текстовый редактор слева, приложение справа

Комментарии:

1. Я бы использовал считыватель stgtream и убедился, что шрифты такие же, как в текстовом редакторе. См.: docs.microsoft.com/en-us/dotnet/api/…

2. @jdweng Я действительно пробовал этот метод. Проблемы, с которыми я столкнулся, заключались в следующем: он печатает на принтере по умолчанию; и б: он печатает код ZPL дословно с любым выбранным шрифтом. Использование журнала печати в WPF. Я не смог найти способ получить имя принтера из системы WPF. Windows. Управления. Распечататьдиалог.

3. Я не знаю, зачем вам нужен документ и абзац. Вы должны иметь возможность печатать без по ссылке. Я бы попробовал объединить ваш существующий код и ссылку без использования каких-либо ненужных методов.

4. Вы вообще не должны использовать этот документ flowdocument. Не для печати. Zpl необходимо передать в исходном виде на принтер zebra, это команды низкого уровня, которые вы отправляете. Например, вы можете взять zpl и отправить его на ip-адрес, на котором работает принтер zebra. Там есть sdk, примеры и форум поддержки. supportcommunity.zebra.com/s/article/…

5. @Энди, ты прав, я пытаюсь отправить необработанный ZPL на принтер. Проблема, с которой я сталкиваюсь, заключается в том, как отправить необработанные данные на принтер. Я думаю, что мне нужно будет создать временный текстовый файл и распечатать его. Я искал способ отправить команду ZPL непосредственно на принтер, выбранный из журнала печати, без создания файла.

Ответ №1:

Я смог решить свою проблему, используя следующий код:

 System.Windows.Controls.PrintDialog prnt = new PrintDialog();            
prnt.PageRangeSelection = PageRangeSelection.AllPages;
prnt.UserPageRangeEnabled = false;

Nullable<bool> result = prnt.ShowDialog();

if (result == true)
{
    ZPL = "<My ZPL>"; // Global string variable
    PrintDocument pdoc = new PrintDocument();
    pdoc.PrintPage  = pdoc_PrintPage;
    pdoc.PrinterSettings.PrinterName = prnt.PrintQueue.FullName; 
    pdoc.Print();
}
 

Затем в событии PrintPage:

 void pdoc_PrintPage(object sender, PrintPageEventArgs ev)
{
    // printFont is a global Font variable set to new Font("Arial", 10)
    ev.Graphics.DrawString(ZPL, printFont, System.Drawing.Brushes.Black, 0, 0, new StringFormat());           
}
 

Теперь моя следующая задача-автоматически выбрать последний использованный принтер в журнале печати.