Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Code working in Delphi 5 fails on Delphi 10.x


This question is answered.


Permlink Replies: 2 - Last Post: May 25, 2017 2:39 PM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Francisco Alvar...

Posts: 83
Registered: 11/10/06
Code working in Delphi 5 fails on Delphi 10.x  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 25, 2017 1:06 PM
Why this code works in Delphi 5 and not in 10.x?
procedure TPackingLblsF1.WriteDisplay(ALine, AMessage: string);
var
  Count: Integer;
  s: String;
begin
  if (UsesDisplay and VaComm2.Active) then
  begin
    Copy(AMessage, 1, 20);                          // Limit message to 20 characters
    {Digit Select <10>, (16), {^P}:Moves the cursor to any position on the display with this
    command followed by a data byte of <00> to <27>, or in decimal (00) to (39).}
    if ALine = '1' then
      begin
        s := #16#00 + AMessage;                     // Move cursor to position 0, first row
        s := s + #13#10;
      end
    else
      begin
        s := #16#20 + AMessage;                     // Move cursor to position 20, second row
        s := s + #13#10;
      end;
    Count := Length(s);
    Count := VaComm2.WriteBuf(s[1], Count);
    if Count = -1 then
      MessageDlg('Error al Escribir en la Torreta', mtError, [mbOk], 0);
    Exit;
  end;
end;

Only displays the first 8 digits and scrolls up, showing only first row.

From Logic Controls manual:
Commands are transmitted to the pole display as ASCII codes. The
command codes listed below are expressed in hexadecimal (base 16)
numbers enclosed inside angle brackets , in decimal numbers
enclosed in parenthesis ( ), and in ASCII characters enclosed in curly
brackets { }. Do not include the brackets as part of the command. ‘ ^ ‘
character denotes ‘Ctrl’ in the keyboard. Press and hold ‘Ctrl’, then
press the next key.
Digit Select <10>, (16), {^P}:
Moves the cursor to any position on the display with this
command followed by a data byte of <00> to <27>, or in decimal
(00) to (39).

Edited by: Francisco Alvarado on May 25, 2017 1:07 PM
Jeff Overcash (...

Posts: 1,529
Registered: 9/23/99
Re: Code working in Delphi 5 fails on Delphi 10.x [Edit]
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 25, 2017 1:13 PM   in response to: Francisco Alvar... in response to: Francisco Alvar...
Francisco Alvarado wrote:
Why this code works in Delphi 5 and not in 10.x?
procedure TPackingLblsF1.WriteDisplay(ALine, AMessage: string);
var
  Count: Integer;
  s: String;
begin
  if (UsesDisplay and VaComm2.Active) then
  begin
    Copy(AMessage, 1, 20);                          // Limit message to 20 characters
    {Digit Select <10>, (16), {^P}:Moves the cursor to any position on the display with this
    command followed by a data byte of <00> to <27>, or in decimal (00) to (39).}
    if ALine = '1' then
      begin
        s := #16#00 + AMessage;                     // Move cursor to position 0, first row
        s := s + #13#10;
      end
    else
      begin
        s := #16#20 + AMessage;                     // Move cursor to position 20, second row
        s := s + #13#10;
      end;
    Count := Length(s);
    Count := VaComm2.WriteBuf(s[1], Count);
    if Count = -1 then
      MessageDlg('Error al Escribir en la Torreta', mtError, [mbOk], 0);
    Exit;
  end;
end;

Only displays the first 8 digits and scrolls up, showing only first row.

From Logic Controls manual:
Commands are transmitted to the pole display as ASCII codes. The
command codes listed below are expressed in hexadecimal (base 16)
numbers enclosed inside angle brackets , in decimal numbers
enclosed in parenthesis ( ), and in ASCII characters enclosed in curly
brackets { }. Do not include the brackets as part of the command. ‘ ^ ‘
character denotes ‘Ctrl’ in the keyboard. Press and hold ‘Ctrl’, then
press the next key.
Digit Select <10>, (16), {^P}:
Moves the cursor to any position on the display with this
command followed by a data byte of <00> to <27>, or in decimal
(00) to (39).

Edited by: Francisco Alvarado on May 25, 2017 1:07 PM

S is a Unicode string in 10.x, in D5 is was an AnsiString. The bytes will not
be the same with the same input.

--
Jeff Overcash (TeamB)
(Please do not email me directly unless asked. Thank You)
Learning is finding out what you already know. Doing is demonstrating that you
know it. Teaching is reminding others that they know it as well as you. We are
all leaners, doers, teachers. (R Bach)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Code working in Delphi 5 fails on Delphi 10.x [Edit]
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 25, 2017 2:34 PM   in response to: Francisco Alvar... in response to: Francisco Alvar...
Francisco Alvarado wrote:

Why this code works in Delphi 5 and not in 10.x?

WriteBuf() works with raw bytes, not characters. Your code is assuming
that Delphi's native String type is still using 8-bit ANSI characters, which
is no longer the case starting in Delphi 2009 onwards, where Char is now
WideChar instead of AnsiChar, and thus SizeOf(Char) is now 2 bytes
instead of 1 byte. Length(String) counts characters, not bytes.

To maintain the original behavior of the code, you need to change your
's' variable from 'String' to 'AnsiString':

procedure TPackingLblsF1.WriteDisplay(ALine, AMessage: string);
var
  Count: Integer;
  s: AnsiString;
begin
  if (UsesDisplay and VaComm2.Active) then
  begin
    Copy(AMessage, 1, 20);                          // Limit message to
20 characters
    {Digit Select <10>, (16), {^P}:Moves the cursor to any position on
the display with this
    command followed by a data byte of <00> to <27>, or in decimal (00)
to (39).}
    if ALine = '1' then
      begin
        s := #16#00 + AnsiString(AMessage);         // Move cursor to
position 0, first row
        s := s + #13#10;
      end
    else
      begin
        s := #16#20 + AnsiString(AMessage);         // Move cursor to
position 20, second row
        s := s + #13#10;
      end;
    Count := Length(s);
    Count := VaComm2.WriteBuf(s[1], Count);
    if Count = -1 then
      MessageDlg('Error al Escribir en la Torreta', mtError, [mbOk], 0);
    Exit;
  end;
end;


Or else encode the 'String' (which is now 'UnicodeString') to bytes
before sending them:

procedure TPackingLblsF1.WriteDisplay(ALine, AMessage: string);
var
  Count: Integer;
  s: String;
  bytes: TBytes;
begin
  if (UsesDisplay and VaComm2.Active) then
  begin
    Copy(AMessage, 1, 20);                          // Limit message to
20 characters
    {Digit Select <10>, (16), {^P}:Moves the cursor to any position on
the display with this
    command followed by a data byte of <00> to <27>, or in decimal (00)
to (39).}
    if ALine = '1' then
      begin
        s := #16#00 + AMessage;                     // Move cursor to
position 0, first row
        s := s + #13#10;
      end
    else
      begin
        s := #16#20 + AMessage;                     // Move cursor to
position 20, second row
        s := s + #13#10;
      end;
    bytes := TEncoding.ASCII.GetBytes(s);
    Count := Length(bytes);
    Count := VaComm2.WriteBuf(bytes[0], Count);
    if Count = -1 then
      MessageDlg('Error al Escribir en la Torreta', mtError, [mbOk], 0);
    Exit;
  end;
end;


Also, just FYI, your call to Copy() does not actually "Limit message to
20 characters", because you are not assigning the result of Copy() back
to 'AMessage'. If you really want to limit the length of the message,
don't discard the result:

AMessage := Copy(AMessage, 1, 20);


Or, use SetLength() instead:

if Length(AMessage) > 20) then
  SetLength(AMessage, 20);


--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02