Solved

Print international charaters in Epson Tm-T70

Posted on 2013-05-16
9
2,613 Views
Last Modified: 2013-05-17
When I print international characters on Epson POS Tm-T20 i have no problem using the class RawPrinterHelper. However when printing on Epson Tm-T70 does not print international characters. But using eg. Chr(128) prints the "Ç" character on TM-T70, correctly.
0
Comment
Question by:rflorencio
  • 4
  • 3
  • 2
9 Comments
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 39171562
Can you show us code you use to send strings to printer?
0
 

Author Comment

by:rflorencio
ID: 39171625
This is the code:

In Dim b1 As String = "ÇÇÇÇÇÇÇÇÇ" & Chr(128) code, "ÇÇÇÇÇÇÇÇÇ" prints a odd character  and Chr(128) prints correctly.


Call RawPrinterClass

      Dim b As Integer = 50

        Dim b1 As String = "ÇÇÇÇÇÇÇÇÇ" & Chr(128)

        Dim s As String
        ''-------------------------------------------------
        s = sess_PT_CHAR1
        s &= "  .: Example :. " & vbCrLf
        s &= "================================" & vbCrLf
        s &= "   EXAMPLE    " & vbCrLf
        s &= b1 & Space(1) & b.ToString & vbCrLf
        s &= sess_EPSON_BOLD_ON
        s &= "* * * END * * *"
        s &= sess_EPSON_BOLD_OFF
        s &= "" & vbCrLf
        s &= "" & vbCrLf
        s &= "" & vbCrLf
        s &= "" & vbCrLf
        s &= "" & vbCrLf
        s &= "" & vbCrLf
        s &= sess_CUT_PAPER
        s &= sess_OPEN_CASH
        Dim xPrintText As New RawPrinterHelper(s)

'-----------------------------------------------------------------------------------


RawPrinterClass
'-----------------------------------------------------------------------------------
Imports System.IO
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices

Public Class RawPrinterHelper
    Public Shared ESC As String = Convert.ToString(ChrW(27))
    Public Shared sess_ESC As String = ChrW(27) + "!"
    Public Shared sess_EPSON_BOLD_ON As String = sess_ESC + Chr(16) + sess_ESC + Chr(32)
    Public Shared sess_EPSON_BOLD_OFF As String = sess_ESC + Chr(0) + sess_ESC + Chr(0)
    Public Shared sess_CUT_PAPER As String = ESC & "@" & ChrW(29) & "V" & ChrW(1)
    Public Shared sess_OPEN_CASH As String = Chr(27) & Chr(112) & Chr(48) & Chr(64) & Chr(64)

Public Shared sess_PT_CHAR As String = Chr(27) & Chr(116) & Chr(0)
'--------------------------------------------------



    ' Structure and API declarions:
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Structure DOCINFOW
        <MarshalAs(UnmanagedType.LPWStr)> Public pDocName As String
        <MarshalAs(UnmanagedType.LPWStr)> Public pOutputFile As String
        <MarshalAs(UnmanagedType.LPWStr)> Public pDataType As String
    End Structure
    <DllImport("winspool.Drv", EntryPoint:="OpenPrinterW", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function OpenPrinter(ByVal src As String, ByRef hPrinter As Integer, ByVal pd As Integer) As Boolean
    End Function
    ' Este código estava a dar um erro foi actualizado nas na framework 4.0 e posterior
    'Public Shared Function OpenPrinter(ByVal src As String, ByRef hPrinter As Integer, ByVal pd As Long) As Boolean
    'End Function
    <DllImport("winspool.Drv", EntryPoint:="ClosePrinter", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
    End Function
    <DllImport("winspool.Drv", EntryPoint:="StartDocPrinterW", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function StartDocPrinter(ByVal hPrinter As IntPtr, ByVal level As Int32, ByRef pDI As DOCINFOW) As Boolean
    End Function
    <DllImport("winspool.Drv", EntryPoint:="EndDocPrinter", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EndDocPrinter(ByVal hPrinter As IntPtr) As Boolean
    End Function
    <DllImport("winspool.Drv", EntryPoint:="StartPagePrinter", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function StartPagePrinter(ByVal hPrinter As IntPtr) As Boolean
    End Function
    <DllImport("winspool.Drv", EntryPoint:="EndPagePrinter", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EndPagePrinter(ByVal hPrinter As IntPtr) As Boolean
    End Function
    <DllImport("winspool.Drv", EntryPoint:="WritePrinter", _
    SetLastError:=True, CharSet:=CharSet.Unicode, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function WritePrinter(ByVal hPrinter As IntPtr, ByVal pBytes As IntPtr, ByVal dwCount As Int32, ByRef dwWritten As Int32) As Boolean
    End Function

    ' 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 or False on failure.
    Public Shared Function SendBytesToPrinter(ByVal szPrinterName As String, ByVal pBytes As IntPtr, ByVal dwCount As Int32) As Boolean
        Dim hPrinter As IntPtr      ' The printer handle.
        Dim dwError As Int32        ' Last error - in case there was trouble.
        Dim di As DOCINFOW          ' Describes your document (name, port, data type).
        Dim dwWritten As Int32      ' The number of bytes written by WritePrinter().
        Dim bSuccess As Boolean     ' Your success code.

        ' Set up the DOCINFO structure.
        With di
            .pDocName = "My Visual Basic .NET RAW Document"
            .pDataType = "RAW"
        End With
        ' Assume failure unless you specifically succeed.
        bSuccess = False
        If OpenPrinter(szPrinterName, hPrinter, 0) Then
            If StartDocPrinter(hPrinter, 1, di) Then
                If StartPagePrinter(hPrinter) Then
                    ' Write your printer-specific bytes to the printer.
                    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, dwWritten)
                    EndPagePrinter(hPrinter)
                End If
                EndDocPrinter(hPrinter)
            End If
            ClosePrinter(hPrinter)
        End If
        ' If you did not succeed, GetLastError may give more information
        ' about why not.
        If bSuccess = False Then
            dwError = Marshal.GetLastWin32Error()
        End If
        Return bSuccess
    End Function ' SendBytesToPrinter()

    ' SendFileToPrinter()
    ' When the function is given a file name and a printer name,
    ' the function reads the contents of the file and sends the
    ' contents to the printer.
    ' Presumes that the file contains printer-ready data.
    ' Shows how to use the SendBytesToPrinter function.
    ' Returns True on success or False on failure.
    Public Shared Function SendFileToPrinter(ByVal szPrinterName As String, ByVal szFileName As String) As Boolean
        ' Open the file.
        Dim fs As New FileStream(szFileName, FileMode.Open)
        ' Create a BinaryReader on the file.
        Dim br As New BinaryReader(fs)
        ' Dim an array of bytes large enough to hold the file's contents.
        Dim bytes(fs.Length) As Byte
        Dim bSuccess As Boolean
        ' Your unmanaged pointer.
        Dim pUnmanagedBytes As IntPtr

        ' Read the contents of the file into the array.
        bytes = br.ReadBytes(fs.Length)
        ' Allocate some unmanaged memory for those bytes.
        pUnmanagedBytes = Marshal.AllocCoTaskMem(fs.Length)
        ' Copy the managed byte array into the unmanaged array.
        Marshal.Copy(bytes, 0, pUnmanagedBytes, fs.Length)
        ' Send the unmanaged bytes to the printer.
        bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, fs.Length)
        ' Free the unmanaged memory that you allocated earlier.
        Marshal.FreeCoTaskMem(pUnmanagedBytes)
        Return bSuccess
    End Function ' SendFileToPrinter()

    ' When the function is given a string and a printer name,
    ' the function sends the string to the printer as raw bytes.
    Public Shared Function SendStringToPrinter(ByVal szPrinterName As String, ByVal szString As String)
        Dim pBytes As IntPtr
        Dim dwCount As 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)
    End Function
    Public Sub New(TextToPrint As String)
        ' TextToPrint - Sequencia de Escape a enviar para impressora ou texto a imprimir
        Dim pd As New PrintDialog()
        ' Open the printer dialog box, and then allow the user to select a printer.
        pd.PrinterSettings = New PrinterSettings()
        If (pd.ShowDialog() = DialogResult.OK) Then
            RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, TextToPrint)
        End If
    End Sub
End Class

Open in new window

0
 
LVL 16

Expert Comment

by:DansDadUK
ID: 39174051
The "Ç" (capital C with cedilla accent) character is defined at Unicode code-point U+00C7.
Unicode is used on most modern operating systems as the "internal" character coding mechanism.

Most printers do not use Unicode directly (since it requires 16-bit character codes), but instead map various 8-bit coded character sets to different sets of (up to 256) glyphs.

The 8-bit coded character set which corresponds directly to the first 256 Unicode code-points is the ISO-8859-1 Latin-1 set, so in this set, the "Ç" character is represented by character-code (hexadecimal) 0xC7, or decimal 199.

The fact that you get the required character printed with a character-code of (decimal) 128 implies that the printer is assuming a coded-character set other than ISO-8859-1.

I'm not familiar with either VB or the Epson printer language, so I don't know how to advise you to select a different coded-character-set on the printer, but I think that this is what you need to do.
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
LVL 16

Expert Comment

by:DansDadUK
ID: 39174066
The Tm-T70 manual (see http://www.juta-soft.hu/pdf/egyeb%20eszkozok/epson%20tm-t70%20felhasznaloi%20kezikonyv.pdf ) refers to use of different character code tables.

Appendix C.1 Page 0 (PC437: USA, Standard Europe (International character set: when “America” is selected)) maps 0x80 (decimal 128) to the "Ç" glyph.

Appendix C.7 Page 16 (WPC1252) maps 0xC7 (decimal 199) to the "Ç" glyph.

This 'code page' appears to be the equivalent of the Windows Latin-1 (codepage 1252) coded character set (which is a superset of ISO-8859-1 (in that graphic characters are assigned to code-points in the range 0x80-0x9F which (in ISO-8859-1) are assigned to the (rarely used) C1 control-code characters).
0
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 39174358
What happens if you change

pBytes = Marshal.StringToCoTaskMemAnsi(szString)

to

pBytes = Marshal.StringToCoTaskMemUni(szString)

Or

pBytes = Marshal.StringToCoTaskMemAuto(szString)
0
 

Author Comment

by:rflorencio
ID: 39174682
CodeCruiser,
If change code only first line is printed.

My problem is that I can do almost everything cut paper, put into expanded, etc.. I can not "say" to printer which is the character table to use. Do not accept this escape sequence
Chr(27) & Chr(116) & Chr(0).
0
 
LVL 16

Accepted Solution

by:
DansDadUK earned 500 total points
ID: 39174768
Surely you need to send the Esc/Pos escape sequence:
Chr(27) & Chr(116) & Chr(16)
to select table 16 (cp1252); selecting table 0 (as per your sequence) will just reselect the American table, which appears to be the default.
0
 

Author Comment

by:rflorencio
ID: 39174931
DansDadUK one more thing,

In fact your sequence works in perfection. However if I put Chr(27) & Chr(116) & Chr(3), also should work with accented characters (or not)?
0
 
LVL 16

Expert Comment

by:DansDadUK
ID: 39175244
Table 3 appears to be code page 860 (Portuguese), which is one of the old National Language Variant sets; it does indeed contain a number of accented characters, but:

- C-cedilla is represented by 0x80 (so your back to the same problem as with the default table 0 character set.

- Code page 1252 (as represented by table 16) matches the 8-bit coded character set used by Windows systems and (apart from the C1 control-code range) that used by *n*x systems as well.
I.e. it matches the character encoding used on your workstation, so it doesn't really make sense to use any other 8-bit set if you want to use characters which are not in the 7-bit ASCII subset.
Of course, if you want to use non-Western languages (e.g. Cyrillic or Thai) then you'd need a different character set or (more likely these days) use Unicode (either UCS-2 or UTF-8 representations), but not all printers support Unicode directly (the Tm-T70 certainly doesn't appear to).
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question