0

I have a problem in Delphi 2010. I would like to send from my PC some Unicode (16 bits) characters to the printer with serial port (COM port). I use the TCiaComPort component in D2010.

For example:

CiaComPort1.Open := True; \\I open the port
Data := #$0002 + UnicodeString(Ж) + #$0003;
CiaComPort1.SendStr(Parancs); //I send the data to the device

If the printer characterset is ASCII then the characters arrive, but the ciril character is '?' on the Printer screen. But if the printer characterset is Unicode then the characters do not arrive to the printer.

An Unicode character represented in 2 bytes. How can I decompose an Unicode character to byte for byte? For example #$0002? And how can I send this strings byte for byte with the comport? Which function?

TLama
  • 75,147
  • 17
  • 214
  • 392
  • Why don't you use the windows interface for printers? – Toon Krijthe May 08 '13 at 19:44
  • 1
    Does `CiaComPort1.SendStr()` accept an `AnsiString` or `UnicodeString` as input? Did you try using a COM port sniffer to make sure that `CiaComPort` is transmitting the actual Unicode bytes as you are expecting? – Remy Lebeau May 09 '13 at 01:44
  • IMHO, it's always a good idea to send raw bytes, handle the encoding and what have you and just send bytes –  May 09 '13 at 06:57
  • `the printer characterset is Unicode` - this is too vague, it could be UTF-8 or UCS-2/UTF-16 – mjn May 09 '13 at 09:56

2 Answers2

0

Does CiaComPort1.SendStr() accept an AnsiString or UnicodeString as input? Did you try using a COM port sniffer to make sure that CiaComPort is transmitting the actual Unicode bytes as you are expecting?

The fact that you are using #$0002 and #$0003 makes me think it is actually not, because those characters are usually transmitted on COM ports as 8-bit values, not as 16-bit values. If that is the case, then that would explain why the Ж character is getting converted to ?, if CiaComPort is performing a Unicode->Ansi data conversion before transmitting. In which case, you may have to do something like this instead:

var
  B: TBytes;
  I: Integer;

B := WideBytesOf('Ж');
SetLength(Data, Length(B)+2);
Data[1] := #$0002;
for I := Low(B) to High(B) do
  Data[2+I] := WideChar(B[I]);
Data[2+Length(B)] #$0003;
CiaComPort1.SendStr(Data); 

However, if CiaComPort is actually performing a data conversion internally, then you will still run into conversion issues for any encoded bytes that are above $7F.

In which case, look to see if CiaComPort has any other sending methods available that allow you to send raw bytes instead of strings. If it does not, then you are pretty much SOL and will need to switch to a better COM component, or just use OS APIs to access the COM port directly instead.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Under Windows (check your OS how to open and write to comm ports), I use the following function to write a UnicodeString to a COMM Port: Bear in mind that the port have to be setup correctly, baud rate, number of bits, etc. See Device Manager => Comm Ports

function WriteToCommPort(const sPort:String; const sOutput:UnicodeString):Boolean;
var
   RetW:DWORD;
   buff: PByte;
   lenBuff:Integer;
   FH:THandle;
begin
   Result:=False;
   lenBuff:=Length(sOutput)*2;
   if lenBuff = 0 then Exit; // Nothing to write, empty string

   FH:= Windows.CreateFile(PChar(sPort), GENERIC_READ or GENERIC_WRITE, 0, Nil, OPEN_EXISTING, 0, 0);
   if (FH <> Windows.INVALID_HANDLE_VALUE) then
   try
      Buff:=PByte(@sOutput[1]);
      Windows.WriteFile(FH, buff^, lenBuff, RetW, Nil);
      Result:= Integer(RetW) = lenBuff;
   finally
      Windows.CloseHandle(FH);
   end;
end;
ja_mesa
  • 1,971
  • 1
  • 11
  • 7