我有一个应用程序,它使用ESC/POS打印机打印收据。需要支持多种语言。目前,我已经测试了中文(繁体和简体)和泰语,它们都可以正常工作。
然而,当我尝试打印越南语时,一些字符被替换成“?”。
这是我的代码:
在打印出来的内容中,一些字符被替换成了“?”(请参见附图)。有什么想法吗?
原始字符串包含
更新2
我决定使用Panagiotis Kanavos的代码,即
这是我将内容(字符串或字节)发送到打印机的方式。
然而,当我尝试打印越南语时,一些字符被替换成“?”。
这是我的代码:
public static readonly string ESC = "\u001B";
...
...
...
Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền thống làm cho lưỡi của bạn";
string toPrint = ESC + "t" + char.ConvertFromUtf32(94) + "\n" + Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(str)); //code page 94 is for vietnamese (WPC1258). It is get from printer
在打印出来的内容中,一些字符被替换成了“?”(请参见附图)。有什么想法吗?
更新
根据Panagiotis Kanavos的评论,我尝试了以下方法:
Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền thống làm cho lưỡi của bạn";
string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(content));
string origStr = enc.GetString(Encoding.GetEncoding("Latin1").GetBytes(newStr));
原始字符串包含
?
。我确认在中文和泰语中,origStr将等于content。但对于越南语来说不是这样的。有什么想法吗?更新2
我决定使用Panagiotis Kanavos的代码,即
bytesToPrint = enc.GetBytes("\x1Bt\x5E\n" + content);
,但它给出了与实际字符不同的?
结果。这是我将内容(字符串或字节)发送到打印机的方式。
[DllImport("Winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("Winspool.drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(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 = "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 = "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 = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(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);
public static bool SendBytesToPrinter(string printerName, IntPtr pBytes, int dwCount, string docName = null, string dataType = "RAW")
{
DOCINFOA di = new DOCINFOA();
di.pDocName = string.IsNullOrWhiteSpace(docName) ? string.Empty : docName;
di.pDataType = string.IsNullOrWhiteSpace(dataType) ? "RAW" : dataType;
IntPtr hPrinter = new IntPtr(0); int dwError = 0, dwWritten = 0; bool bSuccess = false;
if (OpenPrinter(printerName.Normalize(), out hPrinter, IntPtr.Zero))
{
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
dwError = Marshal.GetLastWin32Error();
return bSuccess;
}
public static bool SendBytesToPrinter(string printerName, byte[] bytes, string docName)
{
int dwCount = bytes.Length;
IntPtr ptrBytes = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * bytes.Length);
try
{
Marshal.Copy(bytes, 0, ptrBytes, bytes.Length);
SendBytesToPrinter(printerName, ptrBytes, dwCount, docName);
}
finally { Marshal.FreeCoTaskMem(ptrBytes); }
return true;
}
public static bool SendStringToPrinter(string printerName, string str, string docName)
{
int dwCount = str.Length;
IntPtr ptrBytes = Marshal.StringToCoTaskMemAnsi(str);
try { SendBytesToPrinter(printerName, ptrBytes, dwCount, docName); }
finally { Marshal.FreeCoTaskMem(ptrBytes); }
return true;
}
Encoding.UTF8.GetBytes()
来获取正确的字节。在任何其他情况下,您需要创建一个编码对象,例如使用Encoding.GetEncoding(1258)
,并仅使用其GetBytes()
方法来获取正确的字节。但是,您将失去无法转换为该代码页的任何字符。 - Panagiotis Kanavoschar.ConvertFromUtf32(94)
只是^
字符。该代码将控制码前置到字符串中,具体来说是"\x1Bt^\n"
。\x1B
或\u001b
是相同的字符,即ESC。我怀疑打印机希望控制序列以ESC开头并带有换行符,这意味着你向打印机发送了^t
代码。 - Panagiotis Kanavos