Solución:
He escrito en un blog sobre esto antes después de tener que hacerlo yo mismo. No quiero tocar mi propia bocina demasiado fuerte, pero te recomiendo que leas esa entrada, ya que hablo de un comando de imagen complejo con la impresora. Si puede entender eso, ¡puede imprimir cualquier cosa!
(Hablo de ESC / POS, utilizado en impresoras de recibos minoristas, pero la semántica de la discusión también se aplica a ESC / P, el antiguo lenguaje de matriz de puntos).
En resumen, use un BinaryWriter
en lugar de un string
o te confundirás irremediablemente (como yo) cuando ciertos caracteres se “horneen” con la codificación incorrecta en su camino a la impresora. (¡Confía en mí en este caso! No uses un StringBuilder
al intentar hablar en ESC / POS.)
Tenga cuidado de no utilizar el Write(string)
sobrecarga del BinaryWriter
ya que antepondrá la longitud de la cadena como un byte en la secuencia, que no es lo que desea. (También escribí en un blog sobre eso después de aprenderlo de la manera difícil, también, en el mismo proyecto).
Luego utilizo un código para enviar el byte
matriz, como se obtiene de la BinaryWriter
, directamente a la impresora mediante P / Invocando:
private static void Print(string printerName, byte[] document)
{
NativeMethods.DOC_INFO_1 documentInfo;
IntPtr printerHandle;
documentInfo = new NativeMethods.DOC_INFO_1();
documentInfo.pDataType = "RAW";
documentInfo.pDocName = "Bit Image Test";
printerHandle = new IntPtr(0);
if (NativeMethods.OpenPrinter(printerName.Normalize(), out printerHandle, IntPtr.Zero))
{
if (NativeMethods.StartDocPrinter(printerHandle, 1, documentInfo))
{
int bytesWritten;
byte[] managedData;
IntPtr unmanagedData;
managedData = document;
unmanagedData = Marshal.AllocCoTaskMem(managedData.Length);
Marshal.Copy(managedData, 0, unmanagedData, managedData.Length);
if (NativeMethods.StartPagePrinter(printerHandle))
{
NativeMethods.WritePrinter(
printerHandle,
unmanagedData,
managedData.Length,
out bytesWritten);
NativeMethods.EndPagePrinter(printerHandle);
}
else
{
throw new Win32Exception();
}
Marshal.FreeCoTaskMem(unmanagedData);
NativeMethods.EndDocPrinter(printerHandle);
}
else
{
throw new Win32Exception();
}
NativeMethods.ClosePrinter(printerHandle);
}
else
{
throw new Win32Exception();
}
}
¡Buena suerte!
Pasar por alto el controlador de la impresora y controlar la impresora directamente, utilizando su lenguaje de comandos nativo, es un escenario compatible. El P / Invoke se explica bien en este artículo de KB.
¿Seguro que quieres hacer esto? Es poco común, por decirlo suavemente, que solo se intenta con impresoras térmicas o matriciales de punto de venta de bajo costo. Si no le gusta la mecánica de PrintDocument.PrintPage, a nadie le gusta, podría considerar mi código en este hilo. Tenga en cuenta el método FormFeed.