如何通过USB使用C#将原始ZPL发送到斑马打印机
本文关键字:打印机 ZPL 原始 USB 何通过 使用 | 更新日期: 2023-09-27 18:20:49
我是一名初级C#程序员。我有一个项目需要我通过USB将原始命令发送到Zebra打印机LP2844并使其工作。我做了很多研究,并试图找到一种方法来做到这一点。我使用的代码来自http://support.microsoft.com/kb/322091,但没有起作用。根据我的测试,我似乎已经向打印机发送了命令,但它没有响应并打印。我对此一无所知。有人能帮我吗?
我正在使用按钮直接发送命令
private void button2_Click(object sender, EventArgs e)
{
string s = "A50,50,0,2,1,1,N,'"9129302'"";
// 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, s);
MessageBox.Show("Data sent to printer.");
}
}
EDIT:要解决更新问题,您遇到的问题是使用SendStringToPrinter
,它会向打印机发送ANSI字符串(以null结尾),而这不是打印机所期望的。根据官方EPL2编程指南第23页(根据您的示例,这是您真正在做的,而不是ZPL)。
每个命令行都必须以换行符(LF)字符结束(12月10日)。大多数基于PC的系统在按下Enter键时发送CR/LF按下。回车(CR)字符被打印机忽略并且不能代替LF使用。
因此,您必须修改SendStringToPrinter
以在字符串末尾发送'n
而不是'0
,或者您必须自己构建ASCII字节数组并使用RawPrinterHelper.SendBytesToPrinter
(就像我在下面的原始答案中所做的那样)。
因此,为了修复您发布的简单示例,我们更改了您的函数调用,我们还必须通过发送P1'n
来告诉打印机实际打印
private void button2_Click(object sender, EventArgs e)
{
string s = "A50,50,0,2,1,1,N,'"9129302'"'n";
s += "P1'n";
// Allow the user to select a printer.
PrintDialog pd = new PrintDialog();
pd.PrinterSettings = new PrinterSettings();
if (DialogResult.OK == pd.ShowDialog(this))
{
var bytes = Encoding.ASCII.GetBytes(s);
// Send a printer-specific to the printer.
RawPrinterHelper.SendBytesToPrinter(pd.PrinterSettings.PrinterName, bytes, bytes.Length);
MessageBox.Show("Data sent to printer.");
}
}
//elsewhere
public static class RawPrinterHelper
{
//(Snip) The rest of the code you already have from http://support.microsoft.com/kb/322091
[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten );
private static bool SendBytesToPrinter(string szPrinterName, byte[] bytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false;
di.pDocName = "Zebra Label";
di.pDataType = "RAW";
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
bSuccess = WritePrinter(hPrinter, bytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
throw new Win32Exception(dwError);
}
return bSuccess;
}
}
我用Zebra的旧EPL2语言做到了这一点,但它应该与ZPL非常相似。也许它会让你朝着正确的方向开始。
public class Label
{
#region Print logic. Taken from http://support.microsoft.com/kb/322091
//Snip stuff unchanged from the KB example.
[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten );
private static bool SendBytesToPrinter(string szPrinterName, byte[] Bytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false;
di.pDocName = "Zebra Label";
di.pDataType = "RAW";
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
bSuccess = WritePrinter(hPrinter, Bytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
throw new Win32Exception(dwError);
}
return bSuccess;
}
#endregion
public byte[] CreateCompleteCommand(bool headerAndFooter)
{
List<byte> byteCollection = new List<byte>();
//Static header content describing the label.
if (headerAndFooter)
{
byteCollection.AddRange(Encoding.ASCII.GetBytes("'nN'n"));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("S{0}'n", this.Speed)));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("D{0}'n", this.Density)));
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("q{0}'n", this.LabelHeight)));
if (this.AdvancedLabelSizing)
{
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("Q{0},{1}'n", this.LableLength, this.GapLength)));
}
}
//The content of the label.
foreach (var command in this.Commands)
{
byteCollection.AddRange(command.GenerateByteCommand());
}
//The footer content of the label.
if(headerAndFooter)
byteCollection.AddRange(Encoding.ASCII.GetBytes(String.Format("P{0}'n", this.Pages)));
return byteCollection.ToArray();
}
public bool PrintLabel(string printer)
{
byte[] command = this.CreateCompleteCommand(true);
return SendBytesToPrinter(printer, command, command.Length);
}
public List<Epl2CommandBase> Commands { get; private set; }
//Snip rest of the code.
}
public abstract partial class Epl2CommandBase
{
protected Epl2CommandBase() { }
public virtual byte[] GenerateByteCommand()
{
return Encoding.ASCII.GetBytes(CommandString + ''n');
}
public abstract string CommandString { get; set; }
}
public class Text : Epl2CommandBase
{
public override string CommandString
{
get
{
string printText = TextValue;
if (Font == Fonts.Pts24)
printText = TextValue.ToUpperInvariant();
printText = printText.Replace("''", "''''"); // Replace ' with ''
printText = printText.Replace("'"", "'''""); // replace " with '"
return String.Format("A{0},{1},{2},{3},{4},{5},{6},'"{7}'"", X, Y, (byte)TextRotation, (byte)Font, HorziontalMultiplier, VertricalMultiplier, Reverse, printText);
}
set
{
GenerateCommandFromText(value);
}
}
private void GenerateCommandFromText(string command)
{
if (!command.StartsWith(GetFactoryKey()))
throw new ArgumentException("Command must begin with " + GetFactoryKey());
string[] commands = command.Substring(1).Split(',');
this.X = int.Parse(commands[0]);
this.Y = int.Parse(commands[1]);
this.TextRotation = (Rotation)byte.Parse(commands[2]);
this.Font = (Fonts)byte.Parse(commands[3]);
this.HorziontalMultiplier = int.Parse(commands[4]);
this.VertricalMultiplier = int.Parse(commands[5]);
this.ReverseImageColor = commands[6].Trim().ToUpper() == "R";
string message = String.Join(",", commands, 7, commands.Length - 7);
this.TextValue = message.Substring(1, message.Length - 2); // Remove the " at the beginning and end of the string.
}
//Snip
}
如果人们试图从上面的答案中获得该片段:
[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);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, byte[] pBytes, Int32 dwCount, out Int32 dwWritten);