none
Clase RawPrinterHelper no imprime ñ RRS feed

  • Pregunta

  • Saludos,

    Estoy haciendo uso de la clase RawPrinterHelper, la cual me funciona perfectamente, salvo cuando imprime este no reconoce el caracter ñ, por este sale "±" o " Ã‘ ", adjunto el código y agradezco cualquier ayuda.

        public class RawPrinterHelper
        {
            // Structure and API declarions:
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            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.Unicode, 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.Unicode, 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 = "PrintDoc"; //Este es el nombre con el que guarda el archivo en caso de no imprimir
                // Win7
                di.pDataType = "RAW";//de tipo texto plano
    
                // Win8+
                // di.pDataType = "XPS_PASS";
    
                // 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 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;
            }
        }


    Saludos!!

    domingo, 4 de agosto de 2019 16:35

Respuestas

  • Tienes que hacer tú la conversión de juego de caracteres.

    Cuando imprimes usando los drivers específicos de impresora, por ejemplo, a través de un PrintDocument, entonces puedes pasar un String en Unicode (el formato interno que usa .Net) y los drivers ya saben convertir de Unicode al formato interno que requiera la impresora.

    Pero cuando usas RawPrinter, los bytes que tú envíes pasan directamente a la impresora sin que ningún driver los analice ni los gestione. Esto significa que es tu problema el manipular dichos bytes para que se encuentren en el formato que la impresora requiera para poder imprimir. Cuando haya una ñ, tienes que sustituirla por aquellos bytes que tu marca y modelo de impresora espere que se le transmitan para indicar una ñ. Por desgracia, esto no es universal sino que cambia con cada marca y modelo de impresora, e incluso en muchas de ellas cambia según la configuración actual de la impresora ya que admiten configurarse con distintos juegos de caracteres. Así que no tendrás más remedio que leer el manual de la tuya para ver qué códigos hay que transmitir para la ñ.

    lunes, 5 de agosto de 2019 11:36
    Moderador

Todas las respuestas

  • Tienes que hacer tú la conversión de juego de caracteres.

    Cuando imprimes usando los drivers específicos de impresora, por ejemplo, a través de un PrintDocument, entonces puedes pasar un String en Unicode (el formato interno que usa .Net) y los drivers ya saben convertir de Unicode al formato interno que requiera la impresora.

    Pero cuando usas RawPrinter, los bytes que tú envíes pasan directamente a la impresora sin que ningún driver los analice ni los gestione. Esto significa que es tu problema el manipular dichos bytes para que se encuentren en el formato que la impresora requiera para poder imprimir. Cuando haya una ñ, tienes que sustituirla por aquellos bytes que tu marca y modelo de impresora espere que se le transmitan para indicar una ñ. Por desgracia, esto no es universal sino que cambia con cada marca y modelo de impresora, e incluso en muchas de ellas cambia según la configuración actual de la impresora ya que admiten configurarse con distintos juegos de caracteres. Así que no tendrás más remedio que leer el manual de la tuya para ver qué códigos hay que transmitir para la ñ.

    lunes, 5 de agosto de 2019 11:36
    Moderador
  • Muchas gracias por tu respuesta Alberto, gracias a esto he podido comprender el funcionamiento esto, de casualidad tienes algun enlace o método para  enviar a imprimir mediante PrintDocument directamente a una impresora?

    Saludos!!

    lunes, 5 de agosto de 2019 16:23
  • algun enlace o método para  enviar a imprimir mediante PrintDocument directamente a una impresora?
    Bueno, la cuestión es que con el PrintDocument NO va directamente a la impresora. Lo que haces es dibujar cada una de las páginas en modo gráfico usando GDI+, y una vez que la página está completa entonces entran en juego los drivers de sistema que analizan las instrucciones GDI+ y los convierten en las instrucciones gráficas necesarias para la impresora. Si lo que pretendías es imprimir un ticket a alta velocidad en modo carácter sobre papel contínuo (que es la razón más usual de usar la impresora en modo RAW) entonces el PrintDocument no te sirve.
    • Propuesto como respuesta eRiver1 miércoles, 7 de agosto de 2019 15:11
    martes, 6 de agosto de 2019 11:54
    Moderador
  • Gracias nuevamente por responder Alberto,

    Que método podría utilizar para esto?


    Saludos!!

    jueves, 8 de agosto de 2019 14:27
  • Yo diría que lo más práctico sería seguir usando el RawPrinterHelper, pero antes de enviar los bytes a imprimir, sustituir dentro del array de bytes los códigos que te haya generado para la ñ por los bytes que realmente requiera tu impresora para enviarle una ñ. No hay ninguna forma sencilla de saber cuáles son esos bytes sin leer el manual de la impresora. Por algún sitio tiene que decir cuál es el juego de caracteres que utiliza.
    viernes, 9 de agosto de 2019 7:29
    Moderador