简体   繁体   English

有没有办法使用 Printerutility package 打印西里尔字母? C# 电调/POS

[英]Is there a way to print Cyrillic with Printerutility package? C# ESC/POS

I am trying to print cyrillic letters on my thermal printer but i am unable to do with this example,我正在尝试在我的热敏打印机上打印西里尔字母,但我无法使用此示例,

This code works well with latin letters, but as soon as i change to cyrillic, it prints only "????"此代码适用于拉丁字母,但一旦我更改为西里尔字母,它只会打印“????”

Also when i change 'Encoding.ASCII' to 'Encoding.Unicode' or 'Encoding.Utf8', it prints some random characters.此外,当我将“Encoding.ASCII”更改为“Encoding.Unicode”或“Encoding.Utf8”时,它会打印一些随机字符。

Note: Thermal printer prints cyrillic when i print from word document注意:当我从 Word 文档打印时,热敏打印机打印西里尔字母

Encoding e1 = Encoding.GetEncoding(1251);
PrinterUtility.EscPosEpsonCommands.EscPosEpson obj = new PrinterUtility.EscPosEpsonCommands.EscPosEpson();                 

var BytesValue = e1.GetBytes(string.Empty);
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.CharSize.Nomarl());

BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Alignment.Center());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Separator());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Alignment.Center());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.CharSize.DoubleWidth3());
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("This works"));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.CharSize.Nomarl());
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("Ћирилица\n"));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Separator());
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("This -> љњертзуиопшасдфгхјклчѕџцвбнм work now\n"));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Alignment.Left());
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("Ћирилица\n"));
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("Ћирилица\n"));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Separator());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Alignment.Center());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.BarCode.Code128(barcode));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Separator());
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.CharSize.DoubleHeight3());
BytesValue = PrintExtensions.AddBytes(BytesValue, e1.GetBytes("-------------------Ћирилица-------------------\n"));
BytesValue = PrintExtensions.AddBytes(BytesValue, obj.Alignment.Left());
BytesValue = PrintExtensions.AddBytes(BytesValue, CutPage());

if (File.Exists(".\\tmpPrint.print"))
    File.Delete(".\\tmpPrint.print");

File.WriteAllBytes(".\\tmpPrint.print", BytesValue);

RawPrinterHelper.SendFileToPrinter("BIXOLON SRP-350III", ".\\tmpPrint.print");

try
{
    File.Delete(".\\tmpPrint.print");
}
catch
{
}

public class RawPrinterHelper
{
    // Structure and API declarations:
    [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, ref 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, ref 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;
        Int32 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(), ref 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, ref 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 = 0;

        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 = default(IntPtr);
        Int32 dwCount = default(Int32);
        // 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;
    }
}

''' '''

I managed to solve this by adding 'Encoding e1 = Encoding.GetEncoding(1251);'我设法通过添加'Encoding e1 = Encoding.GetEncoding(1251);'来解决这个问题and replacing 'e1' with 'Encoding.ASCII'.并将“e1”替换为“Encoding.ASCII”。 Also, i had to set default code page for printer to Wpc1251 (Cyrillic).另外,我必须将打印机的默认代码页设置为 Wpc1251(西里尔文)。 I made some screenshots with steps on how to do it我制作了一些屏幕截图,其中包含有关如何操作的步骤

changing code page 1更改代码页 1

changing code page 2更改代码页 2

changing code page 3更改代码页 3

changing code page 4更改代码页 4

The Encodings you are using will not support the ESC/POS Cyrillic code page.您使用的编码不支持 ESC/POS Cyrillic 代码页。
For example, Encoding.ASCII only supports the range from 0x00 to 0x7F.例如,Encoding.ASCII 仅支持从 0x00 到 0x7F 的范围。

Encoding.ASCII Property Encoding.ASCII 属性

An encoding for the ASCII (7-bit) character set. ASCII(7 位)字符集的编码。
ASCII characters are limited to the lowest 128 Unicode characters, from U+0000 to U+007F. ASCII 字符限制为最低 128 个 Unicode 字符,从 U+0000 到 U+007F。
The ASCIIEncoding object that is returned by this property might not have the appropriate behavior for your app.此属性返回的 ASCIIEncoding object 可能没有适合您的应用程序的行为。 It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character.它使用替换回退来用问号(“?”)字符替换无法编码的每个字符串和无法解码的每个字节。


The following three EPSON materials support Cyrillic.以下三种 EPSON 材料支持 Cyrillic。
Page 17 [PC866: Cyrillic #2] 第 17 页 [PC866:西里尔字母 #2]
Page 34 [PC855: Cyrillic] 第 34 页 [PC855:西里尔文]
Page 46 [WPC1251: Cyrillic] 第 46 页 [WPC1251:西里尔文]

The following command switches the printer code page.以下命令切换打印机代码页。
ESC t 电调

Please check if it supports these, as it depends on the vendor/model of the printer you are using.请检查它是否支持这些,因为这取决于您使用的打印机的供应商/型号。


So instead of Encoding.ASCII.GetBytes, you will need to get and use one of the code pages(866/855/1251) supported by the printer with Encoding.GetEncoding Method .因此,您需要使用Encoding.GetEncoding Method获取并使用打印机支持的代码页(866/855/1251)之一,而不是 Encoding.ASCII.GetBytes。

Encoding Class 编码 Class

However, if you are using .NET Core/.NET 5.0 or higher, you will need to call the Encoding.RegisterProvider (EncodingProvider) Method to extend the supported Encoding types in advance.但是,如果您使用的是 .NET Core/.NET 5.0 或更高版本,则需要提前调用Encoding.RegisterProvider(EncodingProvider) 方法来扩展支持的 Encoding 类型。

This is because .NET Core/.NET 5.0 or higher only supports a limited number of types of Encoding.这是因为 .NET Core/.NET 5.0 或更高版本仅支持有限数量的编码类型。
EncodingProvider Class 编码提供者 Class
CodePagesEncodingProvider Class CodePagesEncodingProvider Class


For note:注意:
The reason why Cyrillic characters can be printed with Word document printing is: Word文档打印可以打印西里尔字符的原因是:
Probably because everything is expanded to bit image data before printing.可能是因为在打印之前所有内容都扩展为位图像数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM